Joh*_*itb 20 c++ temporary dot-operator c++11
给出以下场景,将其解释为C++ 0x代码:
struct B { };
struct A { B b; };
int main() {
B const& b = A().b;
/* is the object still alive here? */
}
Run Code Online (Sandbox Code Playgroud)
Clang和GCC(截至2011/02的行李箱版本)表现不同:Clang延长了使用寿命.GCC移动B到新的临时对象,然后将引用绑定到该新临时对象.
我找不到任何一种行为都可以从标准的词汇中得出.表达式A().b不是暂时的(见5.2.5).有人可以向我解释以下内容吗?
谢谢!
650*_*502 11
在N3126 = 10-0116的12.2第5段中,它说:
第二个上下文[其中temporaries在与完整表达式的结尾不同的点被销毁]是指引用绑定到临时的.引用绑定的临时值或作为绑定引用的子对象的完整对象的临时值在引用的生命周期内持续存在,除了...
然后是四个特殊情况列表(ctor-inizializers,参数参数,返回值,新的初始化程序).
所以(在这个版本中)在我看来clang是正确的,因为你将引用绑定到临时的子对象.
考虑到对象的基础子对象,这似乎也是唯一合理的行为.替代方案意味着切入:
Derived foo();
...
void bar()
{
Base& x = foo(); // not very different from foo().b;
...
}
Run Code Online (Sandbox Code Playgroud)
实际上,在做了一个小实验后,似乎确实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;
}
Run Code Online (Sandbox Code Playgroud)
我用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()
Run Code Online (Sandbox Code Playgroud)
在我看来,这是g ++中的一个错误,或者c ++标准要求的错误,如果这确实是预期的行为或可能接受的行为(但我必须告诉我,我并没有真正考虑它,这是只是觉得这种差异有问题).
| 归档时间: |
|
| 查看次数: |
486 次 |
| 最近记录: |