Given a class like this:
class Foo {
public:
Foo(int);
Foo(const Foo&);
Foo& operator=(int);
private:
// ...
};
Are these two lines exactly equivalent, or is there a subtle difference between them?
Foo f(42);
Foo f = 42;
Edit: I confused matters by making the Foo constructor "explicit" in the original question. I've removed that, but appreciate the answers.
I've also added declaration of a copy constructor, to make it clear that copying may not be a trivial operation.
What I really want to know is, according to the C++ standard, will "Foo f = 42" directly call the Foo(int) constructor, or is the copy constructor going to be called?
It looks like fasih.ahmed has the answer I was looking for (unless he's wrong).
-
Foo f = 42;This statement will make a temporary object for the value '42'.
Foo f(42);This statement will directly assign the value so one less function call.
Marcin : That's not true. All modern compilers will create identical code from both of these examples.fasih.ahmed : Just today I was playing with this and modern compilers failed to create identical code. I'm talking latest version of gcc on Linux Enterprise Server 5. Try running that code and you'll find out.Kristopher Johnson : FWIW, I'm less concerned with "create identical code" than the formal equivalence or non-equivalence of the statements.Johannes Schaub - litb : Marcin, but it will still check semantics of the call.Johannes Schaub - litb : even though it optimizes temporariesGorpik : Foo f = 42 is equivalent to Foo f (Foo(42)) in any conforming compiler. If the copy constructor implementation is not available when compiling the call, it cannot be optimised, since the constructor might have side effects.Gorpik : Ups, sorry for the previous comment. According to the standard, the compiler is allowed to do the optimisation even if the copy constructor implementation is not available. So, if the constructor does indeed have side effects, the call is somewhat undefined.Johannes Schaub - litb : Gorphik, it aren't the side effects. even tho there are side effects, the copy can still be elided. the point is the visibility of the copy constructor, and no the compiler is *not* allowed to elide the copy if the copy constructor is not visible. -
class Foo { public: Foo(explicit int); Foo& operator=(int); };That's invalid. The syntax is
class Foo { public: explicit Foo(int); Foo& operator=(int); };The difference is that the conversion constructor cannot be used for implicit conversions when you put explicit before it:
Foo f(10); // works Foo f = 10; // doesn't workThe above doesn't have anything to do with an assignment operator you declared there. It is not used since that is an initialization (only constructors are used). The following will use the assignment operator:
Foo f; f = 10;And will use the default constructor of Foo (the one taking no arguments).
Edit: The questioner changed his question to the specific ways of whether
Foo f = 1; // called "copy initialization" Foo f(1); // called "direct initialization"Are the same. The answer is that they are equivalent to the following:
Foo f(Foo(1)); Foo f(1);If and only if the conversion constructor taking the int is not declared with keyword
explicit, otherwise the first is a compiler error (see above). The compiler is allowed to elide (optimize out) the temporary passed to the copy constructor of Foo in the first case if all semantic restrictions are still safisfied, and even if the copy constructor has side effects. That especially includes a visible copy constructor.fasih.ahmed : Thats what i tried to explain. I guess I failed.Kristopher Johnson : Sorry, I didn't mean to have the "explicit" in the question. I've updated it.Johannes Schaub - litb : still i don't think i will delete that part of my answer. the bottom part answers what your assignment op is forj_random_hacker : Thanks for the detailed explanation. It's rules like "The compiler is allowed to elide... even if the copy ctor has side effects" that make me hate C++ sometimes. I mean, how could they make it any more confusing and potentially damaging???Johannes Schaub - litb : j_random_hacker. i think it's because the copy constructor is used to copy instances. if there is no copy necassary, why should it copy? the cctor should not change any global state anyway (it should just initialize *this). i think it's reasonable to allow the compiler to not make the copy then.
0 comments:
Post a Comment