是否“T const& t = C()。a;延长“a”的寿命。 [英] Does "T const&t = C().a;" lengthen the lifetime of "a"?
问题描述
给出以下场景,解释为C ++ 0x代码:
struct B {};
struct A {B b; };
int main(){
B const& b = A()。
/ *是对象还活着吗? * /
}
Clang和GCC :Clang延长了生命。 GCC将 B
移动到一个新的临时对象,然后将引用绑定到该新的临时对象。
我找不到任何行为可以从标准的词汇衍生出来。表达式 A()。b
不是临时的(见5.2.5)。
- 希望的行为(委员会的意图)
- 从FDIS派生的行为
谢谢!
在N3126 = 10-0116的12.2第5段中,它表示:
其中临时是
在与
的结束不同的点被销毁的全表达式]是当引用
绑定到临时时。引用绑定到的临时
或
临时(即引用
绑定到的子对象的完整对象
)在$ b $的生命周期内仍然存在b引用除了...
,然后遵循四个特殊情况的列表(ctor-inizializers,参考参数,返回值,new因此(在这个版本中)我认为clang是正确的,因为你绑定了一个临时子对象的引用。
EDIT
考虑到对象的基础子对象,这也似乎是唯一合理的行为。替代方法意味着在切片:
Derived foo();
...
void bar()
{
Base& x = foo(); //与foo()没什么区别。
...
}
g ++区分成员子对象和基础子对象,但我不明白在标准中进行这种区分。下面是我使用的测试程序,它清楚可见的两种情况的不同处理...( B
是Base, D
是Derived并且
C
是由)组成。
#include< iostream>
struct B
{
B()
{std :: cout< B {<这个<< } :: B()\\\
; }
B(const B& x)
{std :: cout< B {<这个<< } :: B(const B&<<& x<<)\\\
; }
virtual〜B()
{std :: cout< B {<这个<< } ::〜B()\\\
; }
virtual void doit()const
{std :: cout< B {<这个<< } :: doit()\\\
; }
};
struct D:B
{
D()
{std :: cout< D {<<这个<< } :: D()\\\
; }
D(const D& x)
{std :: cout< D {<<这个<< } :: D(const D&<<& x<<)\\\
; }
virtual〜D()
{std :: cout< D {<<这个<< } ::〜D()\\\
; }
virtual void doit()const
{std :: cout< D {<<这个<< } :: doit()\\\
; }
};
struct C
{
B b;
C()
{std :: cout< C {<<这个<< } :: C()\\\
; }
C(const C& x)
{std :: cout< C {<<这个<< } :: C(const C&<<& x<)\\\
; }
〜C()
{std :: cout< C {<<这个<< } ::〜C()\\\
; }
};
D foo()
{
return D();
}
void bar()
{
std :: cout< 之前调用foo()\\\
;
const B& b = foo();
std :: cout<< 调用foo()\\\
;
b.doit();
std :: cout<< 调用b.doit()\\\
;
const B& b2 = C()。
std :: cout<< 绑定到.b \\\
之后;
b2.doit();
std :: cout<< 调用b2.doit()\\\
;
}
int main()
{
std :: cout< 之前调用bar()\\\
;
bar();
std :: cout<< 调用bar()\\\
;
return 0;
}
我用g ++得到的输出(Ubuntu / Linaro 4.4.4-14ubuntu5) 4.4.5是
在调用bar()之前
在调用foo()之前
B {0xbf9f86ec} :: B()
D {0xbf9f86ec} :: D()
调用foo()后
D {0xbf9f86ec} :: doit()
调用b.doit )
B {0xbf9f86e8} :: B()
C {0xbf9f86e8} :: C()
B {0xbf9f86e4} :: B(const B& 0xbf9f86e8)
C { 0xbf9f86e8} ::〜C()
B {0xbf9f86e8} ::〜B()
绑定到.b
B {0xbf9f86e4} :: doit()
调用b2.doit()
B {0xbf9f86e4} ::〜B()
D {0xbf9f86ec} ::〜D()
B {0xbf9f86ec} b调用bar()后
在我看来,这是一个在g ++中的错误或c ++标准强制要求这是真正的预期行为还是可能的可接受的行为(但我必须告诉我,我没有真正考虑它,这只是一种感觉,这种差异的东西是错误的)。
The following scenario is given, to be interpreted as C++0x code:
struct B { };
struct A { B b; };
int main() {
B const& b = A().b;
/* is the object still alive here? */
}
Clang and GCC (trunk version as of 2011/02) behave differently: Clang lengthens the lifetime. GCC moves B
to a new temporary object, and then binds the reference to that new temporary.
I cannot find either behavior can be derived from the words of the Standard. The expression A().b
is not a temporary (see 5.2.5). Can anyone please explain the following to me?
- Desired behavior (the intent of the committee)
- The behavior as you derive it from the FDIS
Thanks!
In 12.2 paragraph 5 of N3126=10-0116 it's said that:
The second context [ in which temporaries are destroyed at a different point than the end of the full-expression ] is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except ...
and then follows a list of four special cases (ctor-inizializers, reference parameters, returned value, new initializer).
So (in this version) seems to me that clang is correct because you're binding the reference to a subobject of a temporary.
EDIT
Thinking to the base sub-object of an object this also seems to be the only reasonable behavior. The alternative would mean doing a slicing in:
Derived foo();
...
void bar()
{
Base& x = foo(); // not very different from foo().b;
...
}
Actually after making a little experiment seems indeed that g++ differentiates between a member sub-object and a base sub-object, but I don't understand where this differentiation is made in the standard. The following is the test program I used and where it's clearly visible the different handling of the two cases... (B
is Base, D
is Derived and C
is composed).
#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;
}
The output I get with g++ (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5 is
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()
In my opinion this is either a bug in g++ or a bug in what the c++ standard mandates if this is really the expected behavior or a possible acceptable behavior (but I must tell that I didn't really think about it a lot, this is just a feeling that something is wrong with this differentiation).
这篇关于是否“T const& t = C()。a;延长“a”的寿命。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!