1

Here is my situation:

  • I have a class that has a const reference member variable.
  • I attempt to initialize that member variable from a const reference.

My problem is that when the member variable is initialized in-class, a temporary copy of the object in question is made and the address of the temporary is used for the reference. When the member variable is initialized in the constructor initializer list, a copy is not made. Either way the program compiles fine without warnings in g++ 4.8.3 with either the c++11 or c++1y flags.

Below is a minimal program and output. I would just like to understand the rules of this better so I know why it occurs (or if it's a bug).

#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;
}

Sample output:

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
M.M
  • 138,810
  • 21
  • 208
  • 365
Scott
  • 1,176
  • 2
  • 13
  • 19
  • If memory serves, this was a bug in gcc's list-initialization of references, fixed in 4.9. You should be able to reproduce with much simpler code, e.g. `int main() { A a; A const &b { a } ; }` – M.M Sep 08 '16 at 03:29
  • Which compiler version are you using? In this code there's no copies: http://coliru.stacked-crooked.com/a/f30df5ef62b45420 – ABu Sep 08 '16 at 03:30

2 Answers2

2

This is a case of the infamous DR 1288. There was a defect in the published C++11 standard which inadvertently specified that the code:

const A & m_a4{ g_aardvark };

would actually create a temporary from g_aardvark and bind to that. This is nonsense of course, but g++ 4.8 followed the published text. The Standard was repaired by DR 1288 so that the reference binds directly.

Clang always implemented the sensible behaviour, but g++ did not update until the 4.9 chain.

See here for explanation with Standard references and a simpler testcase.

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365
-1

Appears to be a compiler bug as per Peregring-lk above

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

Scott
  • 1,176
  • 2
  • 13
  • 19