C++ C++;:常量上下文中指针数据成员的奇怪行为
方法上的C++ C++;:常量上下文中指针数据成员的奇怪行为,c++,pointers,constants,C++,Pointers,Constants,方法上的const限定符,用于防止数据成员被错误覆盖。如果有一个数据成员是指针,则只保护指针,而不保护指针值。它是C++设计中的缺陷还是它提供的一些基本的东西? 下面是一个演示这种情况的代码。在报告不相关的错误和风格问题之前,请考虑其唯一目的是证明上述情况,并且简短明了。 #include <cstdio> #include <cstdlib> #include <cstring> class Cat { public: Cat(char c
const
限定符,用于防止数据成员被错误覆盖。如果有一个数据成员是指针,则只保护指针,而不保护指针值。它是C++设计中的缺陷还是它提供的一些基本的东西?
下面是一个演示这种情况的代码。在报告不相关的错误和风格问题之前,请考虑其唯一目的是证明上述情况,并且简短明了。
#include <cstdio>
#include <cstdlib>
#include <cstring>
class Cat
{
public:
Cat(char const *name)
: _name(strdup(name))
{ }
~Cat(){ free(_name); }
void SetName(char const *name)
{
free(_name);
_name = strdup(name);
}
char const* GetName() const
{
_name[0] = 'P';
return _name;
}
private:
char *_name;
};
int main()
{
Cat c("lost+found");
c.SetName("Molly");
printf("%s\n",c.GetName());
return 0;
}
结果程序的输出是Polly
更新使用迂腐的
字符常量*
代替传统的常量*
在常量
成员函数中,\u name
的类型变为字符*常量
,这意味着它是常量指针,而不是指针指向的数据
你似乎认为\u name
变成了const char*
。否,常量
适用于指针
,而不是它所指向的数据。因此,\u name
必须变成char*const
为了尽量减少这种混淆,我更喜欢语法
T const
而不是const T
,尽管两者完全相同。因为如果T
是char*
,那么T const
将变成char*const
,而const T
将变成const char*
。前者有助于理解,而后者则使之复杂化。这里提供的最基本的东西就是清晰。指针是类的成员,而它的指针对象不是:当类被自动构造时,它既不会被自动破坏,也不会被自动构造。它可能是一个完全不同的对象,因此当类变为const时,它不一定是const
在这里,您需要类似std::string的东西,即指针的附加语义——例如,保证其内容不会在类之外更改
方法上的常量限定符,用于保护数据成员不被错误覆盖。如果有一个数据成员是指针,则只保护指针,而不保护指针值
您错误地理解了const
限定符的用途。它有三个目的:
- 某个类的const限定实例只能调用该类的const限定成员函数。对于const限定实例,禁止调用非const限定的成员函数
- 常量限定成员函数无法更改实例的直接内容。指向实例外部数据的内容不是实例直接内容的一部分;它们只是不受
限定符的保护const
- 基于以上内容,编译器可以获得大量的优化途径
const
限定符不能保护您作为某个类的作者,不被射中自己的脚(或更高)。它所做的是保护您作为某个类的作者,不受其他人对您的类造成损害,并且允许编译器进行一些非常量设置中不可用的优化。我非常了解它的机制。我想知道为什么这是机械师。为什么不在const
上下文中将\u name
视为char const*const
?我认为这是设计效率低下。或者别的什么…更新了这篇文章。我应该在初始版本中以这种方式编写const
。@Notinlist:我看到了您的编辑。现在char-const*
和const-char*
是一回事。@Notinlist:但我想你把char-char*
和char-const
搞混了。它们是不同的动物。const限定词确实保护了我作为作者不犯错误。这是一个有限的防守,但仍然很重要。const可以被丢弃,所以如果有人想造成伤害,他可以。const限定符可以防止作者或用户的意外错误。没有一个比另一个更重要。指向值不被视为实例内容的概念具有解释价值。但为什么是这个决定,为什么不是另一个?
g++ -W -Wall -Wextra -pedantic -Os pmc.cpp -o pmc