Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are () and {} always equivalent when used for initialization with "new"?

There is a post that deals with parentheses or not after the type name when using new. But what about this:

If 'Test' is an ordinary class, is there any difference between:

Test* test = new Test();
// and
Test* test = new Test{};

Furthermore, suppose Test2 has a constructor for an argument of type Value, is it always equivalent to write:

Value v;
Test2 *test2 = new Test(v);
// and
Test2 *test2 = new Test{v};
like image 820
user1978011 Avatar asked May 03 '15 10:05

user1978011


1 Answers

The general answer is no. The use of a braced-init-list as the initializer will first try to resolve to the constructor that takes an std::initializer_list. As an illustration:

#include <iostream>
#include <vector>
int main() {
  auto p = new std::vector<int>{1};
  auto q = new std::vector<int>(1);
  std::cout << p->at(0) << '\n';
  std::cout << q->at(0) << '\n';
}

Note the semantics of list-initialization (Quoted from cppreference):

  • All constructors that take std::initializer_list as the only argument, or as the first argument if the remaining arguments have default values, are examined, and matched by overload resolution against a single argument of type std::initializer_list
  • If the previous stage does not produce a match, all constructors of T participate in overload resolution against the set of arguments that consists of the elements of the braced-init-list, with the restriction that only non-narrowing conversions are allowed. If this stage produces an explicit constructor as the best match for a copy-list-initialization, compilation fails (note, in simple copy-initialization, explicit constructors are not considered at all)
like image 78
Lingxi Avatar answered Nov 15 '22 21:11

Lingxi