我正在深入研究C ++,并且正在努力使用用文字初始化的const引用。 e.g。
const int &r {100};
它肯定有效,但我想知道编译器使用这种定义做了什么。是否在存储器中创建了一个保持值为100的真实对象?或者在编译期间,每个r
的出现在代码中只被100替换?这是我的猜测,因为初始化程序值在运行时无论如何都无法更改或引用,所以为什么要将它保存在内存中?
答案 0 :(得分:2)
下面:
int
正在创建临时r
,之后绑定到void foo (const std::string& s) {}
foo("test"); // here temporary std::string is created and later on bound to `s`
。对const的引用将延长与其绑定的临时生命周期。
这在以下情况下更有用:
<a>
答案 1 :(得分:1)
理论上(&#34;抽象机器&#34;),文字被创建为临时文件,然后引用被绑定到它,这延长了它的生命。
在实践中,允许编译器改变它,但只要它产生相同的&#34;可观察的行为&#34;。因此编译器没有将变量保存在内存中。
您可以通过比较g++ -O0 -g
与g++ -O3 -g
的输出以及反汇编代码来看到这一点。
短程序:
int main() {
const int &r {100};
return r;
}
我的计算机上的编译时没有优化:
0x00000000004005a8 <+0>: push %rbp
0x00000000004005a9 <+1>: mov %rsp,%rbp
0x00000000004005ac <+4>: mov $0x64,%eax
0x00000000004005b1 <+9>: mov %eax,-0xc(%rbp)
0x00000000004005b4 <+12>: lea -0xc(%rbp),%rax
0x00000000004005b8 <+16>: mov %rax,-0x8(%rbp)
0x00000000004005bc <+20>: mov -0x8(%rbp),%rax
0x00000000004005c0 <+24>: mov (%rax),%eax
0x00000000004005c2 <+26>: pop %rbp
0x00000000004005c3 <+27>: retq
与完全优化相比,内存中显然没有引用(即r只是用文字100代替):
0x00000000004005b0 <+0>: mov $0x64,%eax
0x00000000004005b5 <+5>: retq
答案 2 :(得分:0)
正式地,这会生成一个对象,然后绑定到引用,并且只要引用就生效。
有些情况下必须提供对象。考虑一下您已声明两个函数的情况,这两个函数在单独的翻译单元中定义,如下所示:
void foo(int const*);
bool bar(int const*);
现在你执行以下操作:
int main()
{
const int& r{100};
foo(&r);
return bar(&r);
}
编译器不仅要将指针传递给具有正确值的对象,还必须将指针传递给同一个对象,因为它不知道其他翻译单元中的实现(可能还没有编写),例如:
namespace
{
int const* ptr;
}
void foo(int const* p)
{
ptr = p;
}
bool bar(int const* p)
{
return p == ptr && *p = 100;
}
如果在这种情况下,编译器除了创建一个值为100且绑定到int
的实际r
对象外,还会执行其他操作,结果将不正确。