成员函数末尾的const是什么意思?

86
当在C++中的成员函数(在参数列表之后)的末尾写上const关键字时,它到底意味着什么?
3个回答

98
这意味着在该成员函数内部,*thisconst 的,即它不会改变对象本身。
引用块中提到,关键字 this 是一个 prvalue 表达式,其值是调用函数的对象的地址。类 X 的成员函数中,this 的类型为 X*。如果成员函数声明为 const,则 this 的类型为 const X*。[第 9.3.2 条款 1]
const 成员函数中,通过 const 访问路径访问调用函数的对象;因此,const 成员函数不能修改对象及其非静态数据成员。[第 9.3.2 条款 2]
这意味着可以在类的 const 实例上调用 const 成员函数。但不能在 [1]const 对象上调用非 const 成员函数,因为这可能会尝试修改对象。
注:临时对象只有在其为 const 类型时才是 const 对象。

2
@Mat:同时将您的变量声明为const:const int* ptr = &m_value - Lie Ryan
4
@Mat: 不,这与优化无关。它全部涉及到“const”正确性。任何合理的编译器都能够在应用优化时自行确定什么是常量。此外,声明成员函数为“const”并不会立即帮助编译器,因为“const”可以被强制转换掉(尽管通常不应该这样做)。 - Billy ONeal
2
它在设计库/内部API时非常有用,因为它向API的用户承诺,该成员函数调用不会影响数据。值得注意的是,如果用户出于某种原因拥有该类类型的const变量,则只能使用const成员函数。 - jkerian
2
答案应该是在那个成员函数内*thisconst。它指向的对象(即this所指向的)是const - Ben Jackson
2
实际上,const 表示函数 承诺 不会改变对象。它可以规避甚至违反这个承诺。详细说明按位与逻辑 constness 可能是有用的。同时,对 mutable 的提示也是一个好主意。 - sbi
显示剩余2条评论

41

const在函数签名的结尾表示该函数应假设它是一个成员的对象const。实际上,这意味着你要求编译器检查成员函数不以任何方式更改对象数据。这意味着要求编译器检查它不会直接更改任何成员数据,并且它不会调用任何自身不能保证不更改对象的函数。

当您创建一个const对象时,您要求编译器确保该对象不会超出其初始化范围发生变化。这又意味着编译器将检查您不直接更改其成员数据,且不调用任何未保证不更改对象的函数。

这都是const正确性哲学的一部分。本质上,这意味着如果事情现在工作并且它们不会改变,那么它们永远不会崩溃。换句话说,常量是更可靠地进行工作的。函数签名末尾的这个const工具可以禁止事情破裂,因此您应该尽可能将const放在所有可能的位置。


感谢您的解释。在一个不改变对象的函数中使用const是否有任何反对意见?我觉得,如果您突然决定更改一些设计,并且需要在当前声明为const的函数中调用一个非const函数,软件可能会变得不够灵活可维护,然后可能需要改变一长串调用这个函数的函数。 - Mat
1
没有反对使用const的论据。也就是说,除非您在设计类时立即知道成员函数应该允许更改对象。这是一个设计问题,您应该尽早考虑并且很容易回答。它不是关于“为以后留下余地”的问题。而是关于函数是否应该更改对象或者不应该更改它。这是一个是/否问题,黑白分明,并且回答起来很容易。注意:这不是关于它可能更改对象,而是应该更改对象。 - wilhelmtell
1
这反过来意味着const正确性哲学会让你在函数的每一步上都非常清楚意识到它所做的事情。它迫使你决定并非常明确地了解每个成员函数的存在理由。这是一件好事。你现在要求的是为一个函数留下改变其存在理由的可能性,而这是一件坏事。你应该只改变函数完成任务的方式,而不是它的任务本身。考虑一下你的API的用户(其中也包括你自己)。不要从他们脚底下拉开地毯! - wilhelmtell
1
当用户创建一个const对象时,他们只能在该对象上调用const成员函数。请记住这一点。因此,我们在谈论设计接口:用户可以和不可以调用什么。这是一个早期的决定。如果您没有将函数定义为const,那么您就会“留下一扇门”,从而禁止在const对象情况下调用该函数。用户喜欢const对象,因为对象不会改变,因此不会破坏事物。为允许这种情况进行设计。 - wilhelmtell

12

编译器可以进行优化,但主要的好处在于强制执行函数声明中表达的约定 - 如果你将一个成员函数定义为const,那么编译器会防止在该函数内部修改对象。

你可以通过在其声明中使用mutable来免除类中个别字段的限制。例如,在具有封装自己的lock_guard的类中,即使在const成员函数内,必须更改其值以实现线程安全性时,这非常有用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接