[英]Why can I call a non-const member function pointer from a const method?
[英]C++: Why can I pass a pointer-valued member variable from a const member function to an external function taking a non const pointer parameter?
我正在使用外部库中的函数(这里由printer
函数表示)。
偶然地,我注意到,我可以像print()
函数那样从const
成员函数传递类成员。 即使我编译使用
g++ -Wall -Wextra -Wpedantic -Werror -o test test.cpp
我没有得到错误。
这似乎是非常错误的,因为我实际上是通过调用const
成员函数来修改对象。 为什么编译器没有抱怨? 这是代码:
#include <iostream>
using namespace std;
void printer(void* data) {
static_cast<char*>(data)[0] = '1';
cout << static_cast<char*>(data) << endl;
}
void setUp(char* data, int length) {
for(int i=0; i<length; i++)
data[i] = '0';
data[length] = '\0';
}
class Test {
private:
char* data;
public:
Test(int length) {
data = new char(length+1);
setUp(this->data, length);
}
~Test() {
delete data;
}
void print() const {
printer(this->data);
}
};
int main() {
Test T(3);
T.print();
return 0;
}
我最好的猜测是,编译器只保证指针变量不被修改,即在函数调用后不指向不同的物理地址。 但我也注意到,当我尝试使用std::vector<char>
而不是char*
和修改后的print
函数时,编译器会抛出错误:
void print() const {
printer(this->myVector.data());
}
所以如果我的猜测是正确的,为什么不能对 STL 向量的data()
获得的指针做类似的事情?
您有一个 char* 数据成员。
在 const 限定方法的上下文中,这意味着该成员可能不会发生变异。
该成员是指针。 改变一个指针意味着改变它指向的地方。
为了清楚起见,方法内的有效限定类型是
char * const
而不是
const char *
这就是为了确认你是绝对正确的
我最好的猜测是,编译器只保证指针变量不被修改,即在函数调用后不指向不同的...地址。
但是,对于向量,您想要调用数据再次具有有效限定类型std::vector<char> const&
... 所以您需要std::vector::data
的 const 限定重载,并且返回const char*
。 这是您首先期望的,但它与原始指针的行为不同。
不同的原因是向量是为了表达该数据的所有权而编写的,因此常量向量应该具有常量内容。 原始指针可能拥有它们指向的数据,但没有办法表达这一点,也无法为拥有和不拥有原始指针提供不同的 const 行为。 这是尽可能避免使用原始指针的可能原因之一。
这是允许const
方法更改数据的常用方法。 Test
不变的是指针地址data
; 这不会被print
改变。 尽管如此,您可以自由地改变指针所寻址的内容。
绕过const
方法的另一种方法是将成员声明为mutable
。 可以说,确保内部字符串属性是例如 null 终止用于打印可以被认为是mutable
的合法使用。
在 CppCon 2017 上看到 Kate Gregory 的这篇文章,她提供了一个有趣的例子(一个方法被设计为常量,但稍后添加了缓存): https ://youtu.be/XkDEzfpdcSg?t=854
另请参阅此问题以进行有关该主题的热烈讨论: 除了允许通过 const 函数修改变量之外,'mutable' 关键字是否还有其他用途?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.