我正在研究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
}
所以现在我有两个制作对象的选项,它们彼此互斥。
根据我的理解,如果我使用 options2 ,编译器会在堆栈内存中生成一个临时对象,并将参考值返回给t2。
如果这是对的,我该如何用语言表达或解释 option1 ?似乎在堆栈内存中创建了相同的对象,并且计算机为该对象指定了名称“t2”,但我不清楚 option1 与 option2的不同之处因为变量和引用的名称有些令人困惑。
另外,交替切换选项,我可以看到在每种情况下都在不同的内存位置创建对象。 (例如,option1的对象是在0x7fff5fbff828中创建的,那个或option2是在0x7fff5fbff820中创建的)
请你解释一下
1。变量名(option1)和引用(option2)之间的区别是什么。
2。选项1和2中的工作原理有何不同。
3。为什么在任何一种情况下都会在不同的内存位置创建对象。
提前感谢您的帮助!
答案 0 :(得分:3)
const TestClass t2 = TestClass(100); //option1
const TestClass &t2 = TestClass(100); //option2
选项1:
调用TestClass的复制构造函数,并传入“=”右侧创建的临时文件。复制省略消除了不必要的对象复制(参见下面的Piotrs coment)。
选项2:
您创建了一个对象,即临时对象,该对象将被绑定到引用。
- 变量名(option1)和引用(option2)之间的区别是什么。
醇>
编辑: 我之前不知道这一点,但事实上在选项1中没有第二次分配(感谢Piotr)这是由于复制elision引用了一种编译器优化技术,它消除了不必要的对象复制。
要使用您的文字,“变量名称”是包含数据的内存块。引用就像一个指针,它指向另一个“变量名”,但它必须初始化,并且永远不为null。
- 选项1和2中的工作方式不同。
醇>
正如其他人所说,选项1是静态类型,其中选项2可以指向派生(来自TestClass)对象的实例。
- 为什么在任何一种情况下都会在不同的内存位置创建对象。
醇>
尽管是“相同的”TestObjects(100),但它们是单独的实例,因此位于不同的内存(地址)中
答案 1 :(得分:1)
1)变量名(option1)和。之间的区别是什么 参考(选项2)。
名称具有静态类型。引用可以绑定到派生类 - 我们不知道引用对象的确切类型。
在您的示例中 - 对于选项2 - 您通过创建对它的const引用来延长临时对象的生命周期 - 请参阅http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/
通常,临时对象只会持续到完全结束 它出现的表达方式。但是,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();
}