Copy elision is a compiler optimization in C++ that removes unnecessary copying or moving of objects. Instead of creating temporary objects and then copying them, the compiler constructs the object directly in its final destination.
- It improves performance by eliminating extra copy/move operations
- It is commonly applied in return value scenarios and temporary objects
#include <iostream>
using namespace std;
class Demo {
public:
Demo() { cout << "Constructor\n"; }
Demo(const Demo&) { cout << "Copy Constructor\n"; }
};
Demo createObject() {
return Demo();
}
int main() {
Demo obj = createObject();
return 0;
}
Output
Constructor
Explanation
- The function createObject() returns a temporary Demo object
- Normally, this would trigger copy construction
- With copy elision, the compiler directly constructs obj in main()
- So, the “Copy Constructor” may not be called at all
Types of Copy Elision
Copy elision in C++ is mainly achieved through two compiler optimizations: RVO (Return Value Optimization) and NRVO (Named Return Value Optimization). Both techniques avoid unnecessary copying of objects and directly construct the result in the target location.
Named Return Value Optimization (NRVO)
NRVO happens when a function creates a local object with a name and returns it. Instead of creating a temporary copy of that object, the compiler optimizes the return so that the object is built directly where it is needed.
- Applied when returning a named local object from a function.
- The compiler eliminates copying by constructing the object directly in the caller’s memory.
#include <iostream>
using namespace std;
class GFG {
public:
GFG() {
cout << "Constructor called\n";
}
GFG(const GFG&) {
cout << "Copy Constructor called\n";
}
};
GFG func() {
GFG obj; // Named local object
return obj; // NRVO applied
}
int main() {
GFG obj = func();
return 0;
}
Output
Constructor called
Explanation
- obj is a named local object inside func().
- Normally, returning obj would call the copy constructor.
- With NRVO, the compiler constructs obj directly in main()’s memory.
- So, the copy constructor is usually not called.
Return Value Optimization (RVO)
RVO occurs when a function returns a temporary object instead of a named variable. The compiler removes the intermediate copy step and directly builds the object in the caller’s space.
- Applied when returning a temporary (unnamed) object.
- The compiler constructs the object directly at the return location.
#include <iostream>
using namespace std;
class GFG {
public:
GFG() {
cout << "Constructor called\n";
}
GFG(const GFG&) {
cout << "Copy Constructor called\n";
}
};
GFG func() {
return GFG(); // Temporary object (RVO applied)
}
int main() {
GFG obj = func();
return 0;
}
Output
Constructor called
Explanation
- GFG() creates a temporary unnamed object.
- Without optimization, it would be copied into main().
- With RVO, the compiler constructs it directly in the final location.
- The copy constructor is typically not invoked.
Why Copy Constructor is Not Called
At first glance,
B ob = "copy me";
appears to be equivalent to
B ob = B("copy me");
which suggests that a temporary object should be created and then copied into ob.
However, modern C++ compilers optimize this process by constructing ob directly.
Instead of creating a temporary object, the compiler effectively performs
B ob("copy me");
As a result:
- No temporary object is created.
- The copy constructor is skipped.
- Only the constructor is called.
If compiled with
-fno-elide-constructors
the copy constructor may be invoked (except where copy elision is guaranteed by the language).
Benefits of Copy Elision
Copy elision helps the compiler optimize object creation by avoiding extra copying steps, resulting in faster and more memory-efficient programs.
- Improves performance by removing unnecessary object copies.
- Reduces memory usage by avoiding temporary objects.
- Eliminates overhead of copy and move constructor calls in many cases.
- Makes return-by-value operations efficient in modern C++.
Difference Between RVO and NRVO
| Feature | RVO (Return Value Optimization) | NRVO (Named Return Value Optimization) |
|---|---|---|
| Object Type | Works with temporary objects | Works with named local objects |
| Return Example | return ClassName(); | return obj; |
| Optimization Goal | Eliminates temporary return object | Eliminates copy of local variable |
| How It Works | Directly constructs object in caller’s memory | Reuses named object in return location |
| Guarantee | Often guaranteed in modern C++ (C++17+) | Not always guaranteed |
| Performance Impact | Improves performance by removing copies | Improves performance by removing copies |