【问题标题】:Simple question about C++ constant syntax关于 C++ 常量语法的简单问题
【发布时间】:2011-02-12 16:27:14
【问题描述】:

这是从 Thinking in C++ Vol1 第 10 章复制的一些代码。

   #include <iostream>
   using namespace std;

   int x = 100;

   class WithStatic {
        static int x;
        static int y;
        public:
             void print() const {
             cout << "WithStatic::x = " << x << endl;
             cout << "WithStatic::y = " << y << endl;
           }
  };

函数 print() 的 const 是什么意思?谢谢!

【问题讨论】:

标签: c++ function constants


【解决方案1】:

我之前听说过这被描述为“一种不会在逻辑上改变对象的方法”。这意味着通过调用此方法,调用者可以期望对象的状态在方法返回后保持不变。实际上,this 指针变为指向该类的常量实例的常量指针,因此无法更改成员变量。此规则的例外情况是成员变量使用mutable 声明。如果一个类有mutable 成员变量,则可以通过非常量和常量方法修改这些变量。此外,不能从 const 方法中调用非 const 方法。

有些人使用mutable成员变量来缓存及时计算的结果。理论上,对象的状态不会改变(即唯一的影响是后续调用更快,但在相同输入的情况下它们会产生相同的结果)。

【讨论】:

    【解决方案2】:

    表示它不会改变类的任何成员变量。

    http://www.parashift.com/c++-faq-lite/const-correctness.html

    【讨论】:

      【解决方案3】:

      保证函数根本不会修改对象(即它是“只读”函数)。编辑:显然,该规则的例外是对象是否具有mutable 成员;这些可以通过 const 和 non-const 函数进行更改。

      另外,我很高兴看到其他人向 TIC++ 学习。对于初学者来说,这是一个很好的资源。

      【讨论】:

      • 不完全正确,mutable 成员可以更改。
      • 哦,我不知道mutable 关键字。我会改变我的答案。
      • mutable 是 C++ 的新发展。
      【解决方案4】:

      如果成员函数声明为“const”,则表示该函数不会修改对象的状态。这个:

      • 记录函数不会修改状态的事实(对其他开发人员有用)。
      • 允许编译器进行优化,知道其他“const”函数的结果不会因为调用该函数而改变(这允许函数调用从循环中取出)。
      • 当对象通过 const 引用、const 指针等传递时,可以调用函数。

      由于上述所有原因,作为一般经验法则,如果一个函数没有在逻辑上修改对象的状态,则应该将其声明为“const”。如果对象的逻辑状态发生变化,则不要使用“const”。顺便说一句,在某些情况下,实际状态会改变但逻辑状态不会改变(例如缓存),在这种情况下,仍应将函数标记为“const”,但需要在缓存中使用“mutable”关键字变量,以便告诉编译器修改它们实际上不会改变逻辑状态。

      【讨论】:

        【解决方案5】:

        它的作用是有效地使this 指针成为指向 const 的 const 指针,而不是指向非 const 的 const 指针。因此,任何时候您在 const 成员函数中引用 this - 无论是显式还是隐式 - 您都在使用指向 const 的 const 指针。

        因此,对于您在这里的类,在任何非 const 函数中,this 的类型是 WithStatic const *,而在 const 函数中,它的类型是 const WithStatic * const

        与任何指向 const 的指针一样,您不能更改它指向的任何内容。所以,你不能改变它的任何成员变量,也不能调用它的任何非常量成员函数。

        一般来说,如果可以合理地使成员函数成为 const 是一个好主意,因为它保证您不会改变对象的状态,并且您可以使用 const 对象调用它。

        如果成员变量是mutablevolatile,则可能会被更改,但在您更熟悉语言。当然,您通常不需要担心它们,除非您需要,否则不应使用它们。也可以丢弃 this 指针的常量,此时您可以更改它,但是 IIRC,这是未定义的行为,并且通常被认为是一个坏主意。因此,在某些情况下,可以在 const 成员函数中更改对象的状态,但通常情况下是不可能的,最好避免这样做。

        当您创建一个成员函数 const 时,您实际上是在保证对象的状态不会被该函数调用更改(尽管显然可能会产生副作用,因为您可以调用像 printf() 这样的函数这一事实证明了这一点)。

        【讨论】:

        • 不,volatile 成员不能通过 const 方法更改,只有 mutable 的。 AFAIK,更改非可变成员的唯一方法是使用const_cast
        • 其实没有,this的类型是:const WithStatic *(对于非常量函数)和const WithStatic * const(对于const函数)。指针 const 在星号之后。
        • 好的。指针语法已修复。这就是我讨厌 C++ 指针语法的原因。它变得如此混乱。至于挥发性。不,您不能在 const 函数中更改它,但它可以从您下面更改。因此,它确实适合违背 const 函数的 const 特性的事情,但是不,const 函数本身不能更改 volatile 变量。
        • 指针语法不固定。尝试“在任何非常量函数中,this 的类型为 WithStatic * const”。
        • *叹息*。接得好。它只修复了一半。现在它应该完全修复了。我想我太着急了。 const* T 是迄今为止我将 const 与指针一起使用的最常见方式,这无济于事。指针语法很容易搞砸——尤其是当你赶时间并且没有真正编译你写的东西的时候。谢谢。
        【解决方案6】:

        直观地说,这意味着该方法不会修改调用它的对象。但实际上,这意味着两件事:

        • 可以在声明为const 的对象或对象指针上调用该方法。
        • 在方法内,this 指针变为const。因此,所有成员(除了那些声明为mutable 的成员)在方法的上下文中都是const,即只读。但是,它仍可能会修改:
          • 调用对象的成员所指向的数据
          • 通过this指针以外的方式访问的数据——包括全局数据、方法参数指向的数据、类的静态成员、类的其他对象,甚至是同一个对象(如果碰巧可以访问指向它的非常量指针或使用 const_cast 绕过常量。

        【讨论】:

          【解决方案7】:

          const 表示 print() 不允许修改未标记为 mutable 的状态变量。

          【讨论】:

          • iirc,这是一个可选的编译时检查,所以当你可以时,尝试修改东西是一个非常糟糕的主意。
          • @sreservoir,虽然它只是一个编译时检查,但如果您使用 const_cast 删除,您可以(阅读:不要,因为您承诺不会)修改非 const 成员来自 this 指针的 const。标记为可变的成员可以被修改,而不管成员函数的 const-ness。
          • @sreservoir 是 mutable,而不是 volatile
          • @dreamlax:如果this 指向的对象是在const 创建的(如果它是一个const 全局对象,它甚至可能在只读内存中),这是未定义的行为。如果有人创建了一个指向可写对象的const 指针并将其传递给使用const_cast 的函数,那么一切都会正常进行(除非你做了其他不好的事情,比如给restrict 指针加上别名)。
          • volatile 与此无关。 mutable 是您要查找的关键字。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多