I wrote the code below to verify that popular C ++ 03 compilers implement RVO whenever possible. (See my related question on RVO Return Value Optimization: ho can I avoid creating a copy of the huge STL containers. ).
As far as I understand, the short answer is no. But I'm not sure I understand.
I have the following five questions about the implementation of std :: vector clang gcc and VS9, read the code and the result below:
- Why does the C Fun1 compiler copy a vector twice?
- Why do both B and C compilers always build at least one unsolicited element?
- Why is this unsolicited item executed twice with the C Fun2 compiler?
- Why does space reservation provide another unsolicited element for compilers B and C?
- Is all this a standard match?
- Bonus question: does all this meet user expectations?
#include <iostream>
#include <vector>
#include <cassert>
#define SIZE (3)
class NRVO{
public:
NRVO() : name_(-1){}
~NRVO(){
std::cout << "Destroy "<< name_ << "\n";
}
void set_name(){name_ = counter++;}
private:
int name_;
static int counter;
};
int NRVO::counter = 0;
std::vector<NRVO> fun1(){
std::vector<NRVO> vec(SIZE);
for(std::vector<NRVO>::iterator v_it = vec.begin();
v_it != vec.end();
++v_it){
v_it->set_name();
}
return vec;
}
void fun2(std::vector<NRVO>& vec){
vec.clear();
vec.resize(SIZE);
for(std::vector<NRVO>::iterator v_it = vec.begin();
v_it != vec.end();
++v_it){
v_it->set_name();
}
return;
}
int main(){
{
std::vector<NRVO> myNrvo1;
std::cout << "Fun1\n";
myNrvo1 = fun1();
assert(myNrvo1.size()==SIZE);
}
{
std::vector<NRVO> myNrvo2;
std::cout << "Fun2\n";
fun2(myNrvo2);
assert(myNrvo2.size()==SIZE);
}
{
std::vector<NRVO> myNrvo3;
myNrvo3.reserve(SIZE);
std::cout << "Fun3\n";
fun2(myNrvo3);
assert(myNrvo3.size()==SIZE);
}
return 0;
}
Output using the popular C ++ 11 compiler
Fun1
Destroy 0
Destroy 1
Destroy 2
Fun2
Destroy 3
Destroy 4
Destroy 5
Fun3
Destroy 6
Destroy 7
Destroy 8
Output using the popular C ++ 03 compiler
Fun1
Destroy -1
Destroy 0
Destroy 1
Destroy 2
Destroy 0
Destroy 1
Destroy 2
Fun2
Destroy -1
Destroy 3
Destroy 4
Destroy 5
Fun3
Destroy -1
Destroy -1
Destroy 6
Destroy 7
Destroy 8
Output using the popular C ++ 03 C compiler
Fun1
Destroy -1
Destroy 0
Destroy 1
Destroy 2
Destroy 0
Destroy 1
Destroy 2
Destroy 0
Destroy 1
Destroy 2
Fun2
Destroy -1
Destroy -1
Destroy 3
Destroy 4
Destroy 5
Fun3
Destroy -1
Destroy -1
Destroy -1
Destroy 6
Destroy 7
Destroy 8
source
share