Reputation: 1708
When I initialize an object of my class, both the default and copy constructor are called.
class A
{
public:
A (string s) { str = string (s); cout << "default" << endl; }
A (int n) { cout << "A (int n)" << endl; }
A (string s, int n) { cout << "A (string s, int n)" << endl; }
A (int n2, string s2) { cout << "A (int n2, string s2)" << endl; }
A (const A& a) { str = a.str; cout << "copy" << endl; }
inline void printA () { cout << str << endl; }
string str;
};
int main (void)
{
A a_1 = A ("con 1");
cout << endl;
A a_2 = "con 2";
cout << endl;
A a_3 = A (4);
A a_4 = A ("a_4", 10);
cout << endl;
A a_5 = A (11, "a_5");
cout << endl;
cin.get();
return 0;
}
Result:
default copy default A (int n) A (string s, int n) copy A (int n2, string s2) copy
Why do a_1
, a_3
, and a_4
call both the default and the copy constructors?
A_3 also has a single argument, but it doesn't need copy constructor.
Upvotes: 3
Views: 980
Reputation: 8268
Nobody here knows. You should ask the compiler writer.
Or get another compiler.
There is no fundamental reason for this inconsistent behaviour.
1) compiler behaviour shown is inconsistent
2) only the compiler author could answer this question why compiler behaviour is inconsistent - and maybe not even him, you would need to browse the source code
3) so, the best non-answer is to not waste too much time trying to sort out the reason why the compiler behaviour is inconsistent
4) if the optimisation is important to you, switch compiler
Upvotes: -6
Reputation: 361710
To avoid the superfluous copy constructor calls, eliminate the =
and use this syntax to call the desired constructor directly:
A a_1("con 1");
A a_2("con 2");
A a_3(4);
A a_4("a_4", 10);
A a_5(11, "a_5");
Upvotes: 6
Reputation: 206546
A a_1 = A ("con 1");
Constructs a temporary object by calling the constructor which takes a string as an argument,since the passed type is const char *
the compiler has to perform an implicit conversion first to string
() and then uses this temporary object to copy construct a new a_1
object.
Since there is an additional implicit conversion the compiler cannot optimize this and needs to make the call to the copy constructor.
Based on the comments and further research I am doubtful if the(above italicized)reasoning is correct.
@David suggests in his comments:
the copy can not be elided not because of implicit conversion, but rather because the conversion is explicit. That is, the compiler cannot optimize it because the code explicitly request the creation of the temporary and the copy construction.
However, neither @David nor Me are able to substantiate it through a Standard Citation.
A a_2 = "con 2";
constructs object a_2
by calling the appropriate constructor which takes string as an argument.
A a_3 = A (4);
The note in Case 1 also applies here:
Should Ideally Construct a temporary object by calling the constructor which takes integer as an argument and then use this temporary object to copy construct a new a_3
object as in case 1, but the compiler can optimize and directly construct the object by calling constructor which takes integer as one is available.
A a_4 = A ("a_4", 10);
Constructs a temporary object by calling the constructor which takes string and integer as an argument and then uses this temporary object to copy construct a new a_4
object.
A a_5 = A (11, "a_5");
Constructs a temporary object by calling the constructor which takes integer and string as an argument and then uses this temporary object to copy construct a new a_5
object.
Note that you do not have an Default constructor defined for your class.
You can achieve the same in a more efficient manner by avoiding the creation of the temporary and then copy constructing an object in above cases by not using the assignment(=
).
A a_1("con 1");
A a_2("con 2");
A a_3(4);
A a_4("a_4", 10);
A a_5(11, "a_5");
My Initial answer was on attempt to explain the behavior but as I compile this on gcc-4.3.4 on Ideone, I find that gcc is intelligent enough to optimize the copy constructor call.None of the cases invoke the copy constructor.
The conclusion I come to is, Each compiler depending on its intelligence can or cannot optimize copy constructor calls in such as case, While the Standard does not require the compiler to perform such optimization each compiler evaluates such expressions depending on their capabilities.
If I am wrong on this please free to add me an comment with reasoning.
Upvotes: 5
Reputation: 11028
The reason is that you are doing an implicit conversions. When you construct a_1
, you are using a const char*
, which gets implicitly converted into a std::string
, which is fed into the A
constructor and then copy constructed. When you construct a_3
, there is no implicit conversion involved, so the compiler is allowed to skip the copy constructor and construct a_3
directly with the int
.
Upvotes: 0