C++ 中 this* 的类型

Posted

技术标签:

【中文标题】C++ 中 this* 的类型【英文标题】:the type of this* in C++ 【发布时间】: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 【参考方案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();

【讨论】:

以上是关于C++ 中 this* 的类型的主要内容,如果未能解决你的问题,请参考以下文章

c++和c#中'this'指针的概念和数据类型

C++ _ const的用法,特别是用在函数前面与后面的区别!

C++:对象和类|| this指针对象数组类作用域抽象数据类型章末总结

C++:对象和类|| this指针对象数组类作用域抽象数据类型章末总结

[C++] 通用类型数组

没有类类型 C++