我已经阅读了很多关于这个问题的文章,我从中得到的引用只是别名而且它们不消耗任何内存。编译器用指向变量的地址替换引用。
任何人都可以解释下面的例子会发生什么。编译器如何使用参考ri?
int main()
{
int *pi = new int(50);
int &ri = *pi;
ri = 30;
cout << "val = " << ri << " , " << *pi << endl;
}
它给了我输出:
val = 30 , 30
答案 0 :(得分:3)
int *pi = new int(50);
+----+
pi --> | 50 |
+----+
int &ri = *pi;
+----+
pi --> | 50 | ri = 50, same as *pi, which is 50
+----+
ri = 30; now the contents of what pi points to i.e. *pi is replaced with 30
+----+
pi --> | 30 |
+----+
答案 1 :(得分:2)
编译器可能将引用替换为实际对象:
int main()
{
int *pi = new int(50);
//int &ri = *pi; //compiler might remove this
*pi = 30; //then it replaces ri with *pi
cout << "val = " << *pi << " , " << *pi << endl; //here as well
}
这是编译器可能做的一件事。
答案 2 :(得分:1)
int *pi = new int(50);
你分配一个int对象50;
int &ri = *pi;
你设置一个别名ri到这个int对象,ri是这个对象,pi是对象的地址;
ri = 30;
将30重新分配给int对象;记得ri是int对象;
cout << "val = " << ri << " , " << *pi << endl;
ri和* pi是同一个对象。 您只记得一个对象可能有很多别名,并且使用这些别名中的任何一个都可以操纵该对象。
以及删除的位置。
答案 3 :(得分:1)
引用被定义为别名。标准没有具体说明它们的表示方式,尽管实现方式变化不大。基本上:
让我们看看它是如何翻译的,从你的程序开始:
int main()
{
int *pi = new int(50);
int &ri = *pi;
ri = 30;
std::cout << "val = " << ri << " , " << *pi << std::endl;
}
我们可以消除ri
,因为它绑定的对象是编译器已知的:
int main()
{
int *pi = new int(50);
*pi = 30;
std::cout << "val = " << *pi << " , " << *pi << std::endl;
}
我们可以消除*pi
,因为编译器知道它的最终值:
int main() {
new int(50); // stupid possible side effect usually forbid to optimize this out
std::cout << "val = " << 30 << " , " << 30 << std::endl;
}
我会注意到,在您的示例中,new
调用完全没用,您还可以引用尚未动态分配的对象。
int main() {
int i = 50;
int& ri = i;
ri = 30;
std::cout << "val = " << ri << " < " << i << std::endl;
}
同样有效,没有内存泄漏。
回到表示之间的区别:
void swap(Foo& left, Foo& right);
通常实现为:
void swap(Foo* left, Foo* right);
在这种情况下,引用最终占用(某些)空间(与指针一样多)。
另一方面:
class Object {
public:
Object(): foo(f), f() {}
Foo const& foo;
void set(Foo const& value);
private:
Foo f;
};
编译器通常不给foo
运行时表示。它是const
引用的事实将用于将f
上调用的可能方法限制为不更改它的方法(语义差异),但在运行时它们将直接传递f
。
答案 4 :(得分:0)
ri是一个堆栈变量,就像一个无法分配给新内存地址的指针一样。它主要是一个语义糖,没有什么可以用你不能用指针做的参考你可以做得更安全。当此函数终止时,ri使用的空间将从堆栈中清除。
答案 5 :(得分:0)
引用变量占用堆栈内存,测试它的最佳方法是使用c ++程序的程序集,如下所示.... 编写如下所示的c ++程序并生成它的程序集
#include<iostream>
using namespace std;
int main(){
int i = 100;
int j = 200;
int &x1 = i;
int &x2 = i;
int &x3 = i;
int &x4 = i;
int &x5 = i;
int &x6 = i;
int &x7 = i;
cout << "reference value" << x1 << endl;
return 0;
}
此程序的组装显示堆栈指针向下移动到36字节&#34;这意味着引用获取内存&#34;。
main:
.LFB966:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
pushl %ebx
andl $-16, %esp
subl $64, %esp
movl $100, 28(%esp)
如果您更改上面的cpp程序
#include<iostream>
using namespace std;
int main(){
int i = 100;
int j = 200;
int &x1 = i;
cout << "ref changed" << x1 << endl;
return 0;
}
它的组装显示堆栈指针移动12个字节..
main:
.LFB966:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
pushl %ebx
andl $-16, %esp
subl $32, %esp
movl $100, 20(%esp)
我相信上面的实际可以清除所有事情,如果我错了,请纠正我...... :)