给出了以下情形,将其解释为C++ 0x代码:
struct B { };
struct A { B b; };
int main() {
B const& b = A().b;
/* is the object still alive here? */
}
Clang和GCC(2011/02版的大容量版本)的行为有所不同:Clang延长了生命周期。 GCC将
B
移动到新的临时对象,然后将引用绑定(bind)到该新的临时对象。我找不到任何行为都可以从标准的文字中得出。表达式
A().b
不是临时的(请参阅5.2.5)。谁能向我解释以下内容?谢谢!
最佳答案
在N3126 = 10-0116的12.2第5段中说:
然后列出了四个特殊情况(ctor-inizializer,引用参数,返回值,新的初始化器)的列表。
因此(在此版本中)在我看来clang是正确的,因为您将引用绑定(bind)到临时对象的子对象。
编辑
考虑对象的基本子对象,这似乎也是唯一合理的行为。替代方法将意味着切片:
Derived foo();
...
void bar()
{
Base& x = foo(); // not very different from foo().b;
...
}
实际上,在进行了一些实验之后,g++确实可以区分成员子对象和基础子对象,但是我不知道在标准中在何处进行这种区分。以下是我使用的测试程序,可以清楚地看到这两种情况的不同处理方式...(
B
是Base,D
是Derived,并且C
是组成)。#include <iostream>
struct B
{
B()
{ std::cout << "B{" << this << "}::B()\n"; }
B(const B& x)
{ std::cout << "B{" << this << "}::B(const B& " << &x << ")\n"; }
virtual ~B()
{ std::cout << "B{" << this << "}::~B()\n"; }
virtual void doit() const
{ std::cout << "B{" << this << "}::doit()\n"; }
};
struct D : B
{
D()
{ std::cout << "D{" << this << "}::D()\n"; }
D(const D& x)
{ std::cout << "D{" << this << "}::D(const D& " << &x << ")\n"; }
virtual ~D()
{ std::cout << "D{" << this << "}::~D()\n"; }
virtual void doit() const
{ std::cout << "D{" << this << "}::doit()\n"; }
};
struct C
{
B b;
C()
{ std::cout << "C{" << this << "}::C()\n"; }
C(const C& x)
{ std::cout << "C{" << this << "}::C(const C& " << &x << ")\n"; }
~C()
{ std::cout << "C{" << this << "}::~C()\n"; }
};
D foo()
{
return D();
}
void bar()
{
std::cout << "Before calling foo()\n";
const B& b = foo();
std::cout << "After calling foo()\n";
b.doit();
std::cout << "After calling b.doit()\n";
const B& b2 = C().b;
std::cout << "After binding to .b\n";
b2.doit();
std::cout << "After calling b2.doit()\n";
}
int main()
{
std::cout << "Before calling bar()\n";
bar();
std::cout << "After calling bar()\n";
return 0;
}
我用g++(Ubuntu/Linaro 4.4.4-14ubuntu5)4.4.5获得的输出是
Before calling bar()
Before calling foo()
B{0xbf9f86ec}::B()
D{0xbf9f86ec}::D()
After calling foo()
D{0xbf9f86ec}::doit()
After calling b.doit()
B{0xbf9f86e8}::B()
C{0xbf9f86e8}::C()
B{0xbf9f86e4}::B(const B& 0xbf9f86e8)
C{0xbf9f86e8}::~C()
B{0xbf9f86e8}::~B()
After binding to .b
B{0xbf9f86e4}::doit()
After calling b2.doit()
B{0xbf9f86e4}::~B()
D{0xbf9f86ec}::~D()
B{0xbf9f86ec}::~B()
After calling bar()
我认为这可能是g++中的错误,也可能是c++标准规定的错误,如果这确实是预期的行为或可能的可接受的行为(但是我必须告诉我,我并没有考虑太多,这是只是觉得这种差异出了点问题)。
关于c++ - “T const&t = C().a;”是否会延长 “a”的生命周期?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5689463/