views:

344

answers:

3
int value = 5; // this type of assignment is called an explicit assignment
int value(5); // this type of assignment is called an implicit assignment

What is the difference between those, if any, and in what cases do explicit and implicit assignment differ and how?


http://weblogs.asp.net/kennykerr/archive/2004/08/31/Explicit-Constructors.aspx

EDIT: I actually just found this article, which makes the whole thing a lot clearer... and it brings up another question, should you (in general) mark constructors taking a single parameter of a primitive type - numeric/bool/string - as explicit and leave the rest as they are (of course keeping watch for gotchas such as constructors like (int, SomeType = SomeType())?

+3  A: 

They differ if a class has a constructor marked 'explicit'. Then, one of these does not work.

Otherwise, no difference.

Pavel Radzivilovsky
A: 

Only the first one is an assignment. They are both initialization.

Edit: actually, I'm wrong. Neither are assignment.

Noah Roberts
None of those is an assigment. Assignment and initialization are mutually exclusive terms.
FredOverflow
heh...just as I was editing :P
Noah Roberts
+3  A: 

Neither of these is an assignment of any kind -- they're both initialization. The first uses copy initialization, and the second direct initialization. (FWIW, I'm pretty sure I've never heard the terms "explicit assignment" or "implicit assignment" before).

Edit: (Mostly in response to Nathan's comment):

Here's a corrected version of the code from your comment:

#include <iostream>

struct Foo { 
    Foo() { 
        std::cout << "Foo::ctor()" << std::endl; 
    } 
    Foo(Foo const& copy) { 
        std::cout << "Foo::cctor()" << std::endl; 
    } 
    Foo& operator=(Foo const& copy) { 
        std::cout << "foo::assign()" << std::endl; 
        return *this; 
    } 
};

int main(int, const char**) { 
    Foo f; 
    Foo b(f); 
    Foo x = b;
    return 0; 
}

The result from running this should be:

Foo::ctor()
Foo::cctor()
Foo::cctor()

If you run it and get an foo::assign(), throw your compiler away and get one that works (oh, and let us know what compiler it is that's so badly broken)!

Jerry Coffin
Not *necessarily* true. With a POD type, yes, your statement is accurate. If the type in question was user defined, it's perfectly possible that there's a user-defined assignment operator that does the conversion without there being a similar copy constructor. Odd, yes. However, possible.
Nathan Ernst
Also, the first is assignment. Only the second is initialization. That the first can and will almost assuredly be inlined to an equivalent copy initialization does not detract from it being an assignment. The assumption that copy initialization and copy assignment are the same is flawed and is not guaranteed.
Nathan Ernst
@Nathan: This answer is correct. §8.5/12 defines "copy-initialization" to be any initialization of the form `T x = a;`, and "direct-initialization" to be any initialization of the form `T x(a);`. Both are initialization.
GMan
@Nathan, You have it backwards. Foo bar = baz; will never result in an assignment (unless a constructor happens to be implemented in terms of operator=), it is always copy initialization. It will at most result in code equivalent to `Foo bar(static_cast<Foo>(baz));` and at least result in code equivalent to `Foo bar(baz);`. It will never result in code equivalent to `Foo bar; bar = baz;`. In other words, there is no assignment going on. See section 8.5 14-16 of the draft C++0x standard (N3092) (citing this because I don't have a copy of the current standard but this hasn't changed).
Logan Capaldo
@Nathan Ernst: Absolutely incorrect. Neither form will ever call the assignment operator. These initialization are always handled by constructors (possibly involving conversion operators), but if some constructor is missing the code will not compile. Assignment will never be used instead.
AndreyT
explain this, then:#include <iostream>struct Foo{ Foo() { std::cout << "Foo::ctor()" << std::endl; } Foo(Foo const } Foo return *this; }};int main(int, const char**){ Foo f; Foo b(f); b = Foo(); return 0;Foo::ctor()Foo::cctor()Foo::ctor()foo::assign()
Nathan Ernst
sorry, for the formatting, can't format in comments :/
Nathan Ernst
There is literally an assumption that copy and assignment are functionally equivalent, and the standard does not guarantee this is so. While it is generally so, it is not necessarily so. To arbitrarily make this assumption is incorrect. A compiler can only safely make this assumption when the net results of the two operations are the same (which is actually verifiable).
Nathan Ernst
No one is making the assumption that copy and assignment are functionally equivalent, what you fail to understand is that `T a = b` is _not_ an assignment. Assignment doesn't mean `=` appears in the expression. Specifically, `int value = 5` from the OP is not an assignment as you erroneously state in your comment. Nor will overloading an assignment operator make `T a = b` into an assignment. Add a line like `Foo c = f;` to your example and see if it prints `foo::assign()`. It will not.
Logan Capaldo
@Nathan Ernst: What do you want us to explain in your "explain this" comment? Where do you see the evidence of assignment operator being used for initialization??? The code you posted in the comment works as expected: constructor is used for initialization, assignment operator is used for assignment. You were supposed to demonstrate how assignment operator can be used in initialization. Your code doesn't demonstrate anything like that.
AndreyT