initialize a class object in initializer list

Assume I have a class A, which has two constructors and default copy constructor:
A();
A(int i);


Then in class B, I have a member variable is A:
private A a;

In B constructor, I want to initialize it in initializer list:
1. B():a();
2. B():a(1);
3. B():a(A());
4. B():a(A(1));

My questions is, are all of them legal? If not, which is illegal, and why ?
Thank you in advance.
I'm reluctant because this sounds like a home question. Why don't you put it in some code and compile it to see what the compiler says?
Hi dhayden,

Yes, I agree. I will do a small test to figure out. But actually, I am more interested in 3 and 4. I just saw someone write similarly as 3. But in most cases, we instantiated like:

A a();
A * a = new A(1);

Not very sure how to explain what exactly a(A()) did.

Thanks.
OK, I try all of these. All of them are legal. So for 3, is the procedure as:
(1) A() created an instance of A.
(2) a(A()) constructed the member variable "a" using copy constructor?

Same idea for 4, but using different A constructor in step 1.

Correct ?
Correct. 3 creates a temporary A object with the default constructor, then uses the copy constructor to copy it to "a". This is inefficient and #1 is a better way of initializing "a" with the default constructor. #4 initializes a temporary A object with with A(int) and the uses the copy constructor to copy it to "a". #2 is a better way to initialize "a" with A(int).
> So for 3, is the procedure is:
> (1) A() created an instance of A.
> (2) a(A()) constructed the member variable "a" using copy constructor?


For 3 ( B():a(A()) {} ):

a. copy elision - guaranteed by c++17; permitted, but not mandated in c++14


If a C++11/14 implementation does not apply copy elision

b. if the type A is MoveConstructible:
(1) create an instance of A. (2) construct the member variable "a" using the move constructor

c. otherwise: (1) create an instance of A. (2) construct the member variable "a" using the copy constructor

More information: http://en.cppreference.com/w/cpp/language/copy_elision

Copy elision in action (C++14):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>

struct A
{
    A() { std::cout << "A::A()\n" ; }
    A(int) { std::cout << "A::A(int)\n" ; }
    A( const A& ) { std::cout << "A::A( const A& )\n" ; }
    A( A&& )  { std::cout << "A::A( A&& )\n" ; }
    A& operator=( const A& ) { std::cout << "A& operator=( const A& )\n" ; return *this ; }
    A& operator=( A&& )  { std::cout << "A& operator=( A&& )\n" ; return *this ; }
    ~A() = default ;
};

struct B1 { A a ; } ; // implicitly declared default constructor
struct B2 { A a ; B2() = default ; } ; // explicitly defaulted default constructor

struct B3 { A a ; B3() : a() {} } ; 
struct B4 { A a ; B4() : a( A() ) {} } ;
struct B5 { A a ; B5() : a( A( A( A( A() ) ) ) ) {} } ;

struct B6 { A a ; B6() : a(1) {} } ; 
struct B7 { A a ; B7() : a( A(1) ) {} } ;
struct B8 { A a ; B8() : a( A( A( A( A( A(1) ) ) ) ) ) {} } ; 

int main()
{
   B1 b1 ; // A::A()
   B2 b2 ; // A::A()
   B3 b3 ; // A::A()
   std::cout << "\n---------------\n" ;

   B4 b4 ; // A::A() copy elision
   B5 b5 ; // A::A() copy elision (chained 4 levels deep)
   std::cout << "\n---------------\n" ;

   B6 b6 ; // A::A(int)
   B7 b7 ; // A::A(int) copy elision
   B8 b8 ; // A::A(int) copy elision (chained 5 levels deep)
}

http://coliru.stacked-crooked.com/a/a4fd289ff24b3a2d
Thank you!
Topic archived. No new replies allowed.