C++ 那么,什么是“的类型?”;这是什么?为什么是;这";不是左撇子?

C++ 那么,什么是“的类型?”;这是什么?为什么是;这";不是左撇子?,c++,C++,假设对象是 class A { public : void Silly(){ this = 0x12341234; } 我知道我会得到编译器错误“this”不是左值。但它也不是临时的。那么,“这个”的假设性声明是什么 编译器:mac上的GCC4.2编译器。对于某些X类,this的类型为X*this,但不允许分配给它,因此即使它实际上没有类型X*const this,它的行为几乎就像阻止分配一样。正式地说,它是一个prvalue,与整数文本一样属于同一类别,因此尝试将其赋值大致相当于尝

假设对象是

class A {
public :  void Silly(){
    this = 0x12341234;
}
我知道我会得到编译器错误“this”不是左值。但它也不是临时的。那么,“这个”的假设性声明是什么


编译器:mac上的GCC4.2编译器。

对于某些X类,
this
的类型为
X*this,但不允许分配给它,因此即使它实际上没有类型
X*const this
,它的行为几乎就像阻止分配一样。正式地说,它是一个
prvalue
,与整数文本一样属于同一类别,因此尝试将其赋值大致相当于尝试将不同的值赋值给
'a'
10


<>注意,在早期C++中,<代码> < <代码>是一个LVald——赋值给<代码>这个< /C> > -您这样做是为了处理对象的内存分配,模糊地类似于重载<代码>新< /C> >和<代码>删除<代码>,用于类(当时还不支持)。
不是一个变量-它是一个关键字。当用作右值时,其类型为
a*
a const*
。在现代C++中,禁止使用< <代码> > <代码>。您也不能获取此
的地址。换句话说,它不是一个有效的左值。

您会得到一个编译器错误,因为
这是一个常量指针,指向与该类类型相同的类的实例。虽然可以使用它来更改非常量限定方法、调用方法和运算符中的其他类成员,但不能对其赋值。还要注意,因为它是一个静态方法没有
this
指针的实例

假设的:

class Whatever
{
    // your error because this is Whatever* const this;
    void DoWhatever(const Whatever& obj) { this = &obj; } 

    // this is ok
    void DoWhatever(const Whatever& obj) { *this = obj; }

    // error because this is now: const Whatever* const this;
    void DoWhatever(const Whatever& obj) const { *this = obj; } 

    // error because this doesn't exist in this scope
    static void DoWhatever(const Whatever& obj) { *this = obj; }
};

无法为
提供“声明”。在C++中没有办法“声明”一个rof值。这是一个右值,你已经知道了

左值和右值是产生这些值的表达式的属性,而不是声明或对象的属性。在这方面,人们甚至可以说,宣布左值也是不可能的。您声明了一个对象。左值是将该对象的名称用作表达式时产生的值。从这个意义上说,“声明右值”和“声明左值”都是矛盾修饰法

你的问题似乎还表明,“作为左值”和“作为临时性”的属性在某种程度上是互补的,即所有东西都应该是左值或临时性的。事实上,“暂时性”的财产在这里没有任何意义。所有表达式都是左值或右值。而
这个
正好是一个右值

另一方面,临时值可以被视为右值或左值,这取决于您访问临时值的方式


S.Note,BTW,在C++中(与C相反),普通函数是LValue.< /P> < P>,回答第二部分,“为什么是代码>这个< /代码>不是LValk”,我推测委员会的实际动机,但优点包括:

  • 分配给
    没有太多逻辑意义,因此没有特别需要将其显示在分配的左侧。将其设为右值强调禁止它没有多大意义,这意味着标准不必定义如果你这样做会发生什么
  • 将其设为右值可以防止您将指针指向它,这反过来又免除了为其提供地址的任何需要,就像
    寄存器
    修改的自动变量一样。例如,它可以在非静态成员函数中使用一个寄存器来存储此
  • 。如果使用const引用,则除非使用允许巧妙的优化,否则需要将其复制到具有地址的某个位置,但如果快速连续执行两次,则至少不需要相同的地址,因为如果
    this
    是声明的变量,则需要相同的地址
    出于兴趣,必须
    try{this=madness;}catch(…){this=sparta;}
    哪个编译器会给你这个消息?@Oli:如果代码更改为
    this=(A*)0x12341234,VC++报告“左操作数必须是l值”——有点类似。litb在别处给出了一个很好的例子。假设实例指针被称为
    \u this
    ,我们已经定义了
    \n this(\u this+0)
    @Gman:我不明白你能给我一个参考或链接吗?“当用作右值时,它的类型是
    a*
    a*const
    ”你的意思是
    a*
    a const*
    @Seva:有一个简单的规则可以帮助你保持清晰。如果你看一个声明,比如
    T*p
    T
    是目标类型,
    p
    是指针本身的名称,
    *
    是介于两者之间的“墙”。如果将
    const
    (或
    volatile
    )放在墙的指针一侧,则会影响指针。如果你把它放在墙的“类型”一边,它会影响指针指向的类型。好吧,从C背景来看,我倾向于把右值的声明看作“const-levalue-type”@Ajeet:这真的很奇怪。在这方面,C语言与C++没有太大的不同。在C语言中,
    const int
    声明声明一个左值,而不是右值。虽然不能声明右值,但可以(例如)声明/定义一个类型的左值,该类型的值可以不经过转换就分配给该左值。@AndreyT:Agree。只是我的心理感知把“右值”和“真值”区分开来,前者是常量“左值”,而后者是真正没有地址的临时值。rvalue(const'lvalue')确实有一个地址。只是编译器在它们周围建立了防火墙。@AndreyT:如果函数是左值函数,那么函数赋值就不可能了吗?void f(){}void f1(){}main(){f=f1;}顺便说一句,这会给出一个有趣的错误“can”