变量引用和名称之间的区别

noc*_*lew 9 c++ variables pointers reference

我正在研究c ++的参考,现在我对变量名和引用之间的区别感到很困惑.测试代码如下:

class TestClass{
private:
    int num;
public:
    TestClass(int n):num(n){
        cout<<this<<" : init of : " <<this->num<<endl;
    }

    TestClass(const TestClass& t):num(t.num){
        cout<<this<<" : copyInit of : " <<this->num<<endl;
    }

};

int main(int argc, const char * argv[]){

    TestClass t = *(new TestClass(55)); //just to test copy initialization

    const TestClass t2 = TestClass(100); //option1
    const TestClass &t2 = TestClass(100); //option2


}
Run Code Online (Sandbox Code Playgroud)

所以现在我有两个制作对象的选项,它们彼此互斥.

根据我的理解,如果我使用options2,编译器会在堆栈内存中生成一个临时对象,并将参考值返回给t2.

如果这是对的,我该如何用语言表达或解释选项1?似乎在堆栈内存中创建了相同的对象,并且计算机给该对象命名为't2',但我不清楚这个option1option2的不同之处,因为变量和引用的名称有些令人困惑.

另外,交替切换选项,我可以看到在每种情况下在不同的存储器位置创建对象.(例如,option1的对象是在0x7fff5fbff828中创建的,那个或option2是在0x7fff5fbff820中创建的)

你能解释一下吗?

1.变量名(option1)和引用(option2)之间的区别是什么.

2.选项1和2中的工作方式有何不同.

3.在任何一种情况下,为什么在不同的内存位置创建对象.

提前谢谢你的帮助!

Pio*_*ycz 1

1)变量名(选项1)和引用(选项2)有什么区别。

名称具有静态类型。引用可以绑定到派生类 - 我们不知道引用对象的确切类型。

在您的示例中 - 对于选项 2 - 您通过创建对临时对象的常量引用来延长临时对象的生命周期 - 请参阅http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-最重要的常量/

通常,临时对象仅持续到它出现的完整表达式结束为止。然而,C++ 故意指定将临时对象绑定到堆栈上 const 的引用,将临时对象的生命周期延长到引用本身的生命周期,从而避免常见的悬空引用错误。


2)选项 1 和选项 2 的工作原理有何不同。

如果您调用虚函数 - 那么对于变量名,您知道将调用哪个函数,对于引用 - 您无法知道比您的例子更复杂的示例。


3)为什么在这两种情况下都会在不同的内存位置创建对象。

它们是不同的对象,它们生活在同一时间 - 那么为什么它们的存储位置应该相同?

其他区别是,对于选项 1,您创建了自动变量,对于选项 2,它是临时变量 - 两者可能使用不同的内存(堆栈与寄存器或一些仅用于临时变量的保留内存)


考虑更复杂的例子:

class TestClass{
protected:
    int num;
public:
    TestClass(int n):num(n){
        cout<<this<<" : init of : " <<this->num<<endl;
    }
    TestClass(const TestClass& t):num(t.num){
        cout<<this<<" : copyInit of : " <<this->num<<endl;
    }
    virtual void printNum () const { cout << "NUM: " << num << endl; }
};

class TestClassDerived : public TestClass {
public:
    TestClassDerived(int n):TestClass(n){}
    virtual void printNum () const { cout << "DERIVED NUM: " << num << endl; }
};


int main(int argc, const char * argv[]){
    const TestClass t1 = TestClass(100); //option1
    const TestClass &t2 = TestClassDerived(100); //option2
    t1.printNum();
    t2.printNum();
}
Run Code Online (Sandbox Code Playgroud)

  • @noclew - 对于 1:从派生对象进行的分配称为切片。t2 是在左侧声明的类型 - 它只复制 `TestClassDerived(100)` 的基础部分 - 一般来说你应该避免它:更多细节:http://stackoverflow.com/questions/274626/what-is-the -c 中的切片问题 (3认同)