why copy constructor is called when passing temporary by const reference?
You can find the answer to your question in Copy Constructor Needed with temp object or go directly to http://gcc.gnu.org/bugs/#cxx%5Frvalbind
The C++ Standard says that a temporary
object should be created in this
context and its contents filled with a
copy of the object we are trying to
bind to the reference; it also says
that the temporary copy can be elided,
but the semantic constraints (eg.
accessibility) of the copy constructor
still have to be checked.For further information, you can
consult the following paragraphs of
the C++ standard: [dcl.init.ref]/5,
bullet 2, sub-bullet 1, and
[class.temporary]/2.Starting with GCC 4.3.0, GCC no longer
gives an error for this case. This
change is based on the intent of the
C++ language committee. As of
2010-05-28, the final proposed draft
of the C++0x standard permits this
code without error.
Why does the copy constructor (of a C++ class) get called when a function returns?
The compiler generated copy constructor takes a const
reference as the parameter.
An anonymous temporary is allowed to bind to a const
reference, so compilation passes.
Note that the implied value copy created by return v;
is elided in later C++ standards.
Why is the copy constructor called when we pass an object as an argument by value to a method?
To elaborate the two answers already given a bit:
When you define variables to be "the same as" some other variable, you have basically two possibilities:
ClassA aCopy = someOtherA; //copy
ClassA& aRef = someOtherA; //reference
Instead of non-const lvalue references, there are of course const references and rvalue references. The main thing I want to point out here is, that aCopy
is independent of someOtherA
, while aRef
is practically the same variable as someOtherA
, it's just another name (alias) for it.
With function parameters, it's basically the same. When the parameter is a reference, it gets bound to the argument when the function is called, and it's just an alias for that argument. That means, what you do with the parameter, you do with the argument:
void f(int& iRef) {
++iRef;
}
int main() {
int i = 5;
f(i); //i becomes 6, because iRef IS i
}
When the parameter is a value, it is only a copy of the argument, so regardless of what you do to the parameter, the argument remains unchanged.
void f(int iCopy) {
++iCopy;
}
int main() {
int i = 5;
f(i); //i remains 5, because iCopy IS NOT i
}
When you pass by value, the parameter is a new object. It has to be, since it's not the same as the argument, it's independent. Creating a new object that is a copy of the argument, means calling the copy constructor or move constructor, depending on whether the argument is an lvalue or rvalue.
In your case, making the function pass by value is unnecessary, because you only read the argument.
There is a Guideline from GotW #4:
Prefer passing a read-only parameter by const& if you are only going to read from it (not make a copy of it).
Why does copy constructor get called with this statement: myVector.push_back( A() );
Temporary objects gets destroyed at the end of statement, where they are declared;
A(); // will be destroyed at semicolon;
You need to get the object before destroyed, that's when copy constructor takes into place;
A obj = A(); // A object created and copied into obj before gets destroyed.
Same thing happening with vector push_back
, temporary created and copied into vector
buffer to use it later, before destroyed using copy constructor.
Side effects of passing temporary as const T& and binding to class reference
The c++17 standard §15.2 point 6.9 says
- temporary object bound to a reference parameter in a function call (8.5.1.2) persists until the completion of the full-expression containing the call
So you are good. No UB here auto x= A("E")._s
.
The other issues you have described well yourself. After construction accessing the member will be UB.
You can, however, extend the lifetime of a temporary object by binding it to a local const-reference like so:
struct A {
const std::string& _s;
A(const std::string& s) : _s(s) {}
};
int main(void) {
const std::string& e = "E";
A a(e);
std::cout << a._s << '\n';
}
which would not be UB, but I would not use it like this.
Why is the copy-constructor argument const?
You've gotten answers that mention ensuring that the ctor can't change what's being copied -- and they're right, putting the const there does have that effect.
More important, however, is that a temporary object cannot bind to a non-const reference. The copy ctor must take a reference to a const object to be able to make copies of temporary objects.
Why copy constructor is not called when pass temporary object
In MyClass obj1(MyClass(5));
the compiler elides the temporary object MyClass(5)
because it is allowed to.
In particular, C++ standard 2014 §12.8 para 31, defines cases when copy elision can be performed:
When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects... This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which
may be combined to eliminate multiple copies):
- when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move.
Does binding temporary to a reference require a copy constructor in C++?
So is it necessary to have a copy constructor accessible when binding a temporary to a reference?
Post C++11 - No
Pre C++11 - Yes.
This code compiles fine with GCC 4.7.2 because it is compliant with the C++11 standard.
C++11 standard mandates that when a const reference is initialized from prvalue
, it must be bound directly to the reference object and no temporary is permitted to be created. Also, the copy constructor is not used or required.
Prior to C++11 the rules were different. And this behavior(whether copy constructor will be called) is implementation defined. C++03 allowed the copy constructor being called while binding a const reference to an temporary and hence post C++11 the copy constructor needs to be accessible. Visual C++2010 adheres to the C++03 standard.
Related Topics
Is Using a Vector of Boolean Values Slower Than a Dynamic Bitset
Brute-Force, Single-Threaded Prime Factorization
Implementing Component System from Unity in C++
Access Extern Variable in C++ from Another File
Is There a Reason Why Not to Use Link-Time Optimization (Lto)
How to Access a Global Variable Within a Local Scope
Getprocaddress Function in C++
How to Get Python Exception Text
How to Get a List of Files in a Folder in Which the Files Are Sorted with Modified Date Time
May Volatile Be in User Defined Types to Help Writing Thread-Safe Code
Is Begin() == End() for Any Empty() Vector
Resolving a Circular Dependency Between Template Classes
Compile a Static Binary Which Code There a Function Gethostbyname
Why Function Objects Should Be Pass-By-Value
Program Being Compiled Differently in 3 Major C++ Compilers. Which One Is Right