变量引用和名称之间的差异 我正在学习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 } class测试类{ 私人: int-num; 公众: TestClass(int n):num(n){ 库特

变量引用和名称之间的差异 我正在学习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 } class测试类{ 私人: int-num; 公众: TestClass(int n):num(n){ 库特,c++,variables,pointers,reference,C++,Variables,Pointers,Reference,1) 变量名(选项1)和 参考(选项2) 名称具有静态类型。引用可以绑定到派生类-我们不知道引用对象的确切类型 在您的示例中,对于选项2,您通过创建对临时对象的常量引用来延长临时对象的生存期,请参见 通常情况下,临时对象仅持续到完整场景结束 表达式,但C++故意指定 将临时对象绑定到堆栈上对const的引用 将临时对象的生存期延长到 引用本身,从而避免了在其他情况下可能是常见的引用 悬挂参考错误 2) 在选项1和2中,事情如何不同地工作 若你们调用虚函数,那个么对于变量名,你们知道将调用哪个函

1) 变量名(选项1)和 参考(选项2)

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

在您的示例中,对于选项2,您通过创建对临时对象的常量引用来延长临时对象的生存期,请参见

通常情况下,临时对象仅持续到完整场景结束 表达式,但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();
}
class测试类{
受保护的:
int-num;
公众:
TestClass(int n):num(n){
库特
备选案文1:

调用TestClass的复制构造函数并传入在“=”右侧创建的临时值。复制省略消除了不必要的对象复制(请参见下面的Piotrs coment)

备选案文2:

创建1个对象,即临时对象,该对象将绑定到引用

  • 变量名(选项1)和引用(选项2)之间的区别是什么
  • 编辑: 我以前不知道这一点,但事实上,选项1中没有第二次分配(感谢Piotr),这是由于复制省略,它指的是一种编译器优化技术,可以消除不必要的对象复制

    用你的话来说,“变量名”是一个包含数据的内存块。引用就像一个指针,指向另一个“变量名”,但它必须初始化,并且永远不能为空

  • 在选项1和2中,事情如何不同地工作
  • 正如其他人所说,选项1是静态类型,其中选项2可以指向派生(来自TestClass)对象的实例

  • 在这两种情况下,为什么在不同的内存位置创建对象

  • 尽管是“相同”的TestObjects(100),但它们是单独的实例,因此在不同的内存(地址)

    我想尝试回答这个问题,但你的第三个问题让我困惑……代码是否编译?@Lewsterin如果你重命名第一个选项,它会编译。请注意,
    TestClass t=*(新的TestClass(55))
    您再也不能
    删除分配的内存。@Lews Therin噢,我没有构建两行都包含的代码。我分别测试了每个选项,注释掉了另一个。但问题是每次我测试选项1时,对象都会在内存点A中创建,并在内存点B中使用选项2创建。@Jesse很好,谢谢!我正在测试复制初始化是如何使用这一行的。你能演示一下选项1中的对象是如何更改的吗?我觉得它看起来像
    const
    。有没有证据表明选项1中发生了额外的分配?请看我在ideone上的示例:。没有额外的分配…@PiotrNycz有趣的是,这不是我编写时所期望的。是否因为关于const object?@Caribou非常感谢Caribou。这帮了大忙!然后在实践中,btw/变量名和引用的唯一区别是它们能容纳什么?有趣的是,在这个问题之前,我会跳出来回答是的,但现在我发现自己质疑我认为是真的一切。用你的话来说,“变量名”是包含数据的内存块。该引用就像一个指针,指向另一个“变量名”,但它必须初始化,并且永远不会为空。谢谢你的解释。我能问你更多的细节吗?a1)在回答1中,你能解释更多关于静态类型的信息吗?当我像这样更改你的示例代码“const TestClass t2=TestClassDerived(100);,我可以看到复制初始化发生了,一个超类类型的新对象被分配给了t2。那么,“变量名为静态类型”是否意味着它将始终使用自己的类型来表示对象,方法是将分配的派生对象的副本作为其声明的类型continued@noclew-对于1:您的分配来自派生oBTASE被称为切片。T2是在左侧声明的类型——它只复制了从“代码> TestCaseBasic(100)中的基础部分。一般来说,您应该避免它:更多细节:@ NoCURW - 2:是的,您完全理解它。请考虑:<代码>无效FO(TestCase&t);TestCub派生D(100);Foo(d))。;
    -当您编写
    foo
    的实现时,您不知道其参数的最派生类型。@noclew很好。
    &
    不仅仅是表示对象的方式。
    TestClass(100)
    是在所谓的临时内存中创建的。它可以是一些RAM或寄存器-任何东西-编译器决定它在哪里。当在函数
    测试类t(100)中时;
    创建自动变量-它在我所知道的每个编译器的堆栈上。因此有两个不同的内存-因此不同。此代码:
    const TestClass&t=TestClass(100);
    -j
    const TestClass t2 = TestClass(100); //option1
    const TestClass &t2 = TestClass(100); //option2