1

I found another question which was answered a long time ago and did not really understand one of the answers. Eddie's answer, in his answer he stated that if you used String mystring = 'x'; then x will be converted to an int and call String(int). Why does this statement call the constructor? I thought that in order to use a constructor you had to use a statement like String mystring('x'). Is the assignment operator = equivalent to creating a new instance of an object?

Community
  • 1
  • 1
  • possible duplicate of [What is a converting constructor in C++ ? What is it for?](http://stackoverflow.com/questions/15077466/what-is-a-converting-constructor-in-c-what-is-it-for) –  Oct 19 '14 at 01:30
  • = is not an operator in that statement. – chris Oct 19 '14 at 01:31
  • @chris Could you explain what `=` is in that statement? I've always thought it was assigning the left hand side to the right hand side. – AdaptVPerish Oct 19 '14 at 01:35
  • It's simply not an operator, just an alternative use for the same symbol. Like how `f(a,b)` doesn't use the comma operator if `f` is a function, or how `int *p` doesn't use the dereferencing operator or multiplication operator. It's called copy-initialization. – chris Oct 19 '14 at 01:36
  • @chris I am having a hard time finding documentation on this, say if there was a constructor that accepted 2 arguments, would it be possible to use `=` in that case? – AdaptVPerish Oct 19 '14 at 01:48
  • @AdaptVPerish [cppreference's page on copy initialization](http://en.cppreference.com/w/cpp/language/copy_initialization) gives a good summary. –  Oct 19 '14 at 01:48
  • @AdaptVPerish, Yes, in C++11. `struct S {S(int, int);}; S s = {2, 3};` is classified as copy-initialization. Before that, you could still technically do `S s = S(2, 3);`. – chris Oct 19 '14 at 02:04
  • The title has nothing to do with the question itself. – AlanWik Jan 21 '22 at 17:26

1 Answers1

4

T t(x) is called direct-initialization and T t = x is called copy-initialization. Copy-initialization doesn't use assignment even = is used. Because it's used at the point of declaration it is a form of initialization.

During copy-initialization, if the type of the initializer doesn't match the type of the object being created, then a converting-constructor searched for and called (if available) to convert the initializer. The result is a temporary instance which is either copy or move-constructed into the object.

For example, since 'x' doesn't match the type of String, an appropriate constructor is searched for and used to convert 'x' to a String instance. The String::String(int) constructor is chosen and the result is a temporary instance String('x'). Then (since the temporary is an rvalue), if a move-constructor is available, the temporary will be move-constructed into mystring and otherwise copy-constructed.

if there was a constructor that accepted 2 arguments, would it be possible to use = in that case?

Yes, you can use a braced-initializer to supply multiple arguments. It will search for the best constructor for each argument:

struct Square
{
    Square(float width, float height);
};

int main()
{
    // copy-initialization:
    Square square = {2.5, 4.0}; // calls Square(2.5, 4.0)
}

But note that if there is a constructor that takes std::initializer_list of the same type, then that will override the behavior shown above: it will call the initializer list constructor instead.

David G
  • 94,763
  • 41
  • 167
  • 253
  • Just a quick query on the example you just showed: Isn't there anything like `move-initialization`? If yes, then I think, your comment should say `move-initialization` instead of `copy-initialization` as the temporary will be moved to create `square` object. Am I right or missed something? – aniliitb10 Jan 25 '18 at 10:45
  • @aniliitb10 Yes it would be more accurate to say move-initialization, but when we say "copy" we mean it could either be an actual copy or a move. But it turns out that in the example I showed, a copy/move doesn't occur since I'm using list-initialization. It's no different than using direct-list-initialization (`Square square{2.5, 4.0}`). – David G Jan 25 '18 at 16:49