Best practice to construct an Instance

Viewed 89

In C++, I notice that initialization is a complicated topic for me. I came across maybe five different ways to construct an instance, and that's got me confused. When do I have to use one way over another way?

class A
{
private:
    int x;
    float y;
    
public:
    A(int xa, float ya) { x = xa; y = ya; };
};

int main()
{
    A a = A(1, 2);
    
    A b = {1, 2};
    
    A c(1, 2);
    
    A d = A{1, 2};

    A e{1, 2};
}
1 Answers

Like @Eljay said, Nicolai Josuttis covers this thoroughly in "The Nightmare of Initialization in C++.

Usually curly braces initialization does the right thing. It prevents the most vexing parse and narrowing conversions.

For your example, this would be

A c{1,2.0};

The main problem that comes to mind is when it's ambiguous if you wanted the initializer list constructor or the n-argument constructor:

std::vector<std::size_t> x{100, 30};
std::vector<std::size_t> y(100, 30);

What is x.size()? y.size()? I believe x.size()==2 and y.size()==100.

In this situation, personally, I would write a helper function to construct the vector of n copies of the same element so I don't have to think about the subtle difference between these:

temmplate<class T>
auto vector_of_n_copies(std::size_t n, T) {
  auto const v = std::vector<T>(n,T);
  assert(v.size()==n);
  return v;
}

Additionally, you should initialize in the constructor via member initialization like this:

class A{
  int x;
  float y;
 public:
  A(int xa, float ya): x{xa}, y{ya} {}
};

From C++ Core Guidelines, C.49: Prefer initialization to assignment in constructors,

Reason An initialization explicitly states that initialization, rather than assignment, is done and can be more elegant and efficient. Prevents “use before set” errors.

Related