6

I've seen a statement according to which

string noun("ants");
string noun = "ants";

are exactly equivalent.

This is contrary to my intuition: I thought in the second case a conversion occurs (via a constructor of the string class), then the assignment operator gets called with an argument of class string. What is there actually happening ?

5
  • 7
    C++ is happening, that's what. It's initialization in both cases, so no call to op= is made. Compare to string noun; noun = "ants"; Commented May 6, 2014 at 11:07
  • 2
    As the saying goes: Initialization is not assignment. Commented May 6, 2014 at 11:10
  • There's no assignment anywhere, but the two are still not exactly equivalent; see Joachim Pileborg's answer. Commented May 6, 2014 at 11:16
  • this is why you should add a copy constructor to your classes. Some people add an assignment operator and wonder why it is never called. Commented May 6, 2014 at 11:18
  • 1
    @clambake Or ban copy and assignment. (This is what I do most of the time for polymorphic types.) Commented May 6, 2014 at 11:20

2 Answers 2

9

For initialization of a variable definition using assignment, like

std::string a = "foo";

Here two objects are created: The variable you define (a in my example) and a temporary object (for the string "foo"). Then the copy-constructor of your variable (a) is called with the temporary object, and then the temporary object is destructed. The copy-assignment operator is not called.

However, the copying can be avoided if the compiler uses copy elision, which is an optimization technique to avoid unnecessary copies and copying. The copy-constructor needs to be there anyway, even if it's not called.


For the definition

std::string a("foo");

there is a better constructor which takes a pointer to a constant string, which the literal "foo" can be seen as (string literals are actually constant arrays of char, but like all arrays they decay to pointers).

Sign up to request clarification or add additional context in comments.

4 Comments

Agreed, "copy constructor" gets called in both cases.
This is not what happens. Two objects are not created.
@Michael Conceptually, yes. The standard contains special language which allows the compiler to elide the extra object, even if it cannot prove that the copy constructor only copies, and most, if not all implementations do.
@Michael, try deleteing the copy-constructor or making it private, then your compiler should give an error for the second version.
3

I thought it would be harder to find, but here goes:

§12.6.1 Explicit initialization ([class.expl.init])

complex a(1);   // initialize by a call of
                // complex(double)
complex b = a;  // initialize by a copy of a

As @pmr pointed out, initialization is not assignment, thus no call to an assignment operator is made. Refer to the rest of 12.6.1 for details.

Valuable information can also be found in §8.5 ([dcl.init]), with 8.5.1 denoting

initializer:
    brace-or-equal-initializer
    ( expression-list )
brace-or-equal-initializer:
    = initializer-clause
    braced-init-list

and 8.5.2 showing examples of initializers.

Disclaimer: I only had n3485 laying around, but I doubt it changed in C++14

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.