给出了以下情形,将其解释为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)。谁能向我解释以下内容?
  • 所需的行为(委员会的意图)
  • 从FDIS的行为

  • 谢谢!

    最佳答案

    在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/

    10-11 18:40