4

我编写了下面的代码来检查流行的 C++03 编译器是否尽可能实现 RVO。(请参阅我关于 RVO返回值优化的相关问题:我可以避免复制构建巨大的 STL 容器。)。

据我了解,简短的回答是否定的。但我不确定我是否理解。

关于 clang gcc 和 VS9 的 std::vector 实现,我有以下五个问题,请阅读下面的代码和输出:

  1. 为什么编译器 C Fun1 将向量复制两次?
  2. 为什么编译器 B 和 C 总是构造至少一个非请求元素?
  3. 为什么这个非请求元素用编译器 C Fun2 生成两次?
  4. 为什么保留空间会为编译器 B 和 C 产生一个非请求元素?
  5. 所有这些标准都符合吗?
  6. 奖励问题:这一切是否符合用户的期望?

#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;
}

使用流行的 C++11 编译器 A 输出

Fun1
Destroy 0
Destroy 1
Destroy 2
Fun2
Destroy 3
Destroy 4
Destroy 5
Fun3 
Destroy 6
Destroy 7
Destroy 8

使用流行的 C++03 编译器 B 输出

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

使用流行的 C++03 编译器 C 输出

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
4

0 回答 0