【问题标题】:What is the meaning of a const at end of a member function? [duplicate]成员函数末尾的 const 是什么意思? [复制]
【发布时间】:2011-05-02 21:01:01
【问题描述】:

当 C++ 中的 const 关键字写在成员函数的末尾(参数列表之后)时,它到底是什么意思?

【问题讨论】:

    标签: c++ constants


    【解决方案1】:

    这意味着*this 在该成员函数内部是const,即它不会改变对象。

    关键字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 成员函数,因为它可能会尝试修改它。

    [1] 注意:临时对象不是const 对象,除非它是const 类型。

    【讨论】:

    • @Mat:将您的变量也声明为 const:const int* ptr = &m_value
    • @Mat:不,它与优化无关。这一切都与const 正确性有关。任何合理的编译器都将能够自己弄清楚在应用优化时什么是不变的。另外,声明一个成员函数const 并不能立即帮助编译器,因为const 可以被const_cast 编辑掉。 (虽然一般来说你不应该那样做)。
    • 它在设计库/内部 API 时最有用,因为它向所述 API 的用户承诺此成员函数调用不会与数据混淆。还值得注意的是,如果用户出于某种原因拥有该类类型的 const 变量,则他们只能使用 const 成员函数。
    • 答案应该是*this 是该成员函数内的const。它是 const 的对象(this 指向的对象)。
    • 实际上,const 表示函数承诺不会改变对象。它可以规避甚至违反承诺。详细说明按位与逻辑常量可能很有用。提示mutable 可能也是一个好主意。
    【解决方案2】:

    const 在函数签名的末尾意味着该函数应该假定它所属的对象是const。实际上,这意味着您要求编译器检查该成员函数不会以任何方式更改对象数据。这意味着要求编译器检查它是否没有直接更改任何成员数据,并且它不会调用任何本身不保证不会更改对象的函数。

    当您创建const 对象时,您要求编译器确保该对象在其初始化之后不会更改。这反过来意味着编译器将检查您是否没有直接更改其成员数据,并且您不会调用任何不能保证它不会更改对象的函数。

    这都是 const 正确性 哲学的一部分。从本质上讲,这意味着如果事情现在正常运行并且它们不会改变,那么它们将永远不会破裂。换句话说,恒定的事物更容易可靠地处理。函数签名末尾的这个const 是一个工具,可以让你禁止事情被破坏。这反过来意味着您应该将const 放在任何可能的地方。

    【讨论】:

    • 感谢您的解释。有没有反对在不改变对象的函数中使用 const 的论据?我觉得如果您突然决定例如更改某些设计并需要在当前声明为 const 的函数中调用非 const 函数,然后可能必须更改调用此函数的一大串函数,那么软件的可维护性可能会降低太
    • 不,没有理由反对使用const。也就是说,除非您现在知道,在设计类时,应该允许成员函数更改对象。这是一个你应该尽早问自己的设计问题,而且应该很容易回答。这不是“让门稍后打开”。相反,它是关于函数是应该改变对象还是不应该改变它。这是一个是/否的问题,黑色或白色,中间没有任何内容,应该很容易回答。注意:不是可以改变对象,而是应该
    • 这反过来意味着 const-correctness 哲学迫使你在早期就非常清楚每个函数的作用。它迫使您决定并非常清楚每个成员函数的存在理由。这是好事。您要问的是为更改功能的存在理由敞开大门,这是一件坏事。你应该只改变如何一个函数得到它应该做的事情,而不是做什么它。想想你的 API 的用户(也就是你自己)。不要把地毯从他们的脚上扯下来!
    • 当用户创建const 对象时,他们只能在该对象上调用const 成员函数。记住这一点。所以我们在这里讨论的是设计一个界面:用户可以调用什么,不可以调用什么。这是一个早期的决定。如果您通过未将函数定义为 const 来“打开门”,那么您将禁止在 const 对象环境中调用该函数。用户喜欢const 对象,因为对象不会改变,因此不会破坏事物。允许这样做的设计。
    【解决方案3】:

    编译器优化是可能的,但主要好处是强制执行函数声明中表达的契约 - 如果您将成员函数定义为 const,编译器会阻止对该函数内的对象进行任何修改。

    您可以在声明中使用mutable 使类中的各个字段不受此限制。例如,当您有一个封装了自己的 lock_guard 的类时,这很有用,即使在 const 成员函数中也必须更改其值以强制线程安全。

    【讨论】:

      猜你喜欢
      • 2011-03-09
      • 2015-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-20
      • 2013-05-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多