【问题标题】:the type of this* in C++C++ 中 this* 的类型
【发布时间】:2014-12-22 16:15:50
【问题描述】:

这听起来可能很愚蠢。在 C++prime 第 5 版 P258 中,它说:

默认情况下,this 的类型是指向类类型的非常量版本的 const 指针。例如,默认情况下,Sales_data 成员函数中 this 的类型是 Sales_data *const。

我可以理解 this* 是一个 const 指针,这意味着它指向的对象一旦初始化就不能改变。但是它说:

虽然这是隐式的,但它遵循正常的初始化规则,这意味着(默认情况下)我们不能将 this 绑定到 const 对象。

但我写了以下代码,它仍然编译得很好:

class Test{
public:
    Test() = default;
    Test(const string &s): teststr(" ") {};
    Test(int a) : testint(a) {};
    Test(const string &s, int a): teststr(s), testint(a) {};
    string getstr() const { return teststr; };
    int getint() { return testint; };   //there is no const here
private:
    string teststr;
    int testint = 0;
};

int main(){
    Test a("abc",2);

    cout << a.getint() << " ";
    cout << a.getstr() << endl;
    cout << endl;

    return 0;
}

所以我的问题是: 如果编译器可以很好地编译它是否有'const',为什么这很重要? 然后书上说:

毕竟 isbn 的主体不会改变 this 指向的对象,所以如果 this 是指向 const 的指针,我们的函数会更灵活。

我想知道灵活性是什么?你能给我举几个例子吗?

【问题讨论】:

  • 这本书具有误导性。 this 不是“常量指针”。它是一个关键字,在评估时会产生一个合适指针类型的纯右值。既然是prvalue,就不能修改,就像不能说(1 + 2) = 3一样。
  • 您混淆了“const 指针”(不能指向不同对象的指针)和“指向 const 的指针”(指向不允许更改的对象的指针指针)。
  • 至于你想要的例子,把你的main()的第一行改成const Test a("abc",2);,你会注意到你不能再调用getint()但是你可以 继续拨打getstr()。不改变对象的方法应该声明为const,因为这样它们就可以在给定const对象(或引用/指向const对象)时使用。
  • 您的引用特别指出“默认情况下,this 的类型是一个 const 指针指向类类型的非 const 版本。例如,默认情况下,this 的类型在 Sales_data 成员函数中是 Sales_data *const"
  • 你一直在输入this* 这不是一回事。请简单的this

标签: c++ pointers const-pointer


【解决方案1】:

对于初学者来说,this 通常被描述为一个常量指针。

然而this实际上是一个指针类型的prvalue(纯右值)。您不能将任何东西分配给基本类型的纯右值,这意味着 this 的“常量性”。

this 的确切类型取决于方法的 cv 限定。经验法则是 cv-qualification 只是简单地添加到通常的指针类型之前 - 即,如果 Class 的方法标记为 const,则类型为 const Class*

如果编译器可以编译它是否有 'const' 或 不是,这有什么关系?

如果(且仅当)this 的指针类型为const,则不能修改该类的成员。

Class const* ptr; // ptr->data is also const, not modifiable through this pointer

Class* ptr; // ptr->data isn't const - can be modified.

方法上的const-qualifier 允许您区分const 对象的方法和非const 对象的方法,这通常是必需的。

【讨论】:

    【解决方案2】:

    根据 C++ 标准(9.3.2 this 指针)

    1 在非静态 (9.3) 成员函数的主体中,关键字 this 是一个纯右值表达式,其值是对象的地址 该函数被调用。成员函数中 this 的类型 X 类是 X*。如果成员函数声明为 const,则其类型 this 是 const X*,如果成员函数声明为 volatile,则 this 的类型是 volatile X*,并且如果声明了成员函数 const volatile,this的类型是const volatile X*。

    如您所见,没有任何内容表明 this 的类型为 ClassTYpe * constClassType const * const。它是一个纯右值,除了可以调用非 const 成员函数的类类型的纯右值外,不能修改为任何纯右值。

    至于你,你混合了两种类型,一个常量指针和一个指向常量数据的指针。 比如这个声明

    const ClassType *p;
    

    不声明常量指针。所以指针本身可能没有初始化。另一方面是声明

    ClassTYpe * const p = new ClassTYpe;
    

    声明一个常量指针,并且指针本身应该被初始化为任何其他常量。

    至于你书中的这句话

    毕竟,isbn 的主体不会改变 this 的对象 点,所以如果这是一个指针,我们的函数会更灵活 为常量

    那么这意味着最好用限定符const来定义函数。在这种情况下,可以为常量和非常量对象调用它。否则它可能只为非常量对象调用,因为在函数中this 的指针类型不是const ClassTYpe *

    【讨论】:

    • "它是一个纯右值,不能被修改为任何纯右值" 这只适用于非类类型的纯右值,所以 "any" 错了。
    • @Lightness Races in Orbit 您可以为类类型的prvlaue 调用非常量成员函数,但您不能直接更改该类的数据成员。
    • 正确,但您可以通过调用成员函数来做到这一点。说你不能修改对象是完全错误的。
    【解决方案3】:

    “灵活性”是您可以在任何对象上调用const 函数,无论是否为常量。您不能在 const 对象(或指向 const 的引用/指针)上调用非 const 函数。

    所以下面会失败:

    const Test c;
    cout << a.getint() << " ";   // ERROR: non-const function
    cout << a.getstr() << endl;  // OK: const function
    

    除了这种灵活性之外,声明成员函数const 也是一个好主意,因为这样可以防止您在不应该修改的函数中意外修改对象。

    【讨论】:

      【解决方案4】:

      “我可以理解 this* 是一个 const 指针,这意味着它所指向的对象一旦初始化就不能改变。但是它说:”

      不,你搞错了。作为this 一个 const 指针 意味着,你不能像改变指针值本身一样

       class MyClass {
            void foo() {
                MyClass a;
                this = &a; // <<< Compiler error
            }
       }
      

      this 的类型实际上显示为

       MyClass * const this;
      

      对于const 实例或引用

       MyClass const * const this;
      

      Note this is different from

       const MyClass* some_const_instance_pointer;
      

      【讨论】:

      • "注意这与"你错了。完全没有区别。:)
      • 虽然你更新了你的帖子,但我看不出有什么不同。:)
      【解决方案5】:

      两个问题两个答案。

      this 指针无法重新分配。在这种情况下,这就是 const 的含义。您可以更改this 指向的对象的内容,但不能更改它指向的对象。

      创建方法const 的额外灵活性在于它可以用于const 和非常量对象。不能在 const 对象上使用非常量方法。

      例子:

      class A {
          int a;
          public:
          int method() const {
              return a;
          }
      };
      
      void f() {
          A a;
          const A ca;
      
          a.method();
          ca.method();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-11-30
        • 1970-01-01
        • 1970-01-01
        • 2021-06-25
        • 1970-01-01
        • 2011-11-06
        • 2023-03-18
        • 1970-01-01
        相关资源
        最近更新 更多