C ++ 11类内引用成员初始化会导致错误复制

时间:2016-09-08 03:26:15

标签: c++ c++11 gcc reference list-initialization

以下是我的情况:

  • 我有一个具有const引用成员变量的类。
  • 我尝试从const引用初始化该成员变量。

我的问题是,当成员变量在类中初始化时,会生成相关对象的临时副本,并将临时地址用于引用。在构造函数初始值设定项列表中初始化成员变量时,不会生成副本。无论哪种方式,程序在g ++ 4.8.3中使用c ++ 11或c ++ 1y标志编译时都没有警告。

以下是最小程序和输出。我想更好地理解这个规则,所以我知道它为什么会发生(或者它是一个错误)。

#include <iostream>
using namespace std;
struct A
{
    A( )
    {
        cout << "creating an A at " << this << endl;
    }

    A( const A & a )
    {
        cout << "copying an A from instance at " << & a << " to instance at " << this << endl;
    }
};

A g_aardvark;

const A & GetAardvark( )
{
    cout << "returning an A at " << & g_aardvark << endl;
    return g_aardvark;
}

struct B
{
    B( )
        : m_a1( GetAardvark( ) )
        , m_a2( g_aardvark )
    { }
    const A & m_a1;
    const A & m_a2;
    const A & m_a3{ GetAardvark( ) };
    const A & m_a4{ g_aardvark };
};

int main( )
{
    B butter;
    cout << "B has m_a1 at " << & butter.m_a1 << endl;
    cout << "B has m_a2 at " << & butter.m_a2 << endl;
    cout << "B has m_a3 at " << & butter.m_a3 << endl;
    cout << "B has m_a4 at " << & butter.m_a4 << endl;
    return 0;
}

示例输出:

creating an A at 0x601494
returning an A at 0x601494
returning an A at 0x601494
copying an A from instance at 0x601494 to instance at 0x7fffc595f87f
copying an A from instance at 0x601494 to instance at 0x7fffc595f87e
B has m_a1 at 0x601494
B has m_a2 at 0x601494
B has m_a3 at 0x7fffc595f87f
B has m_a4 at 0x7fffc595f87e

2 个答案:

答案 0 :(得分:2)

这是臭名昭着的DR 1288的案例。已发布的C ++ 11标准存在缺陷,无意中指定了代码:

const A & m_a4{ g_aardvark };

实际上会从g_aardvark创建一个临时值并绑定到该临时值。这当然是无稽之谈,但g ++ 4.8遵循已发布的文本。标准由DR 1288修复,以便参考直接结合。

Clang总是实现明智的行为,但g ++直到4.9链才更新。

See here有关标准参考和更简单的测试用例的解释。

答案 1 :(得分:-1)

根据Peregring-lk上面的

,似乎是一个编译器错误

http://coliru.stacked-crooked.com/a/f30df5ef62b45420