如何在不调用复制构造函数的情况下使用类初始化STL向量/列表

War*_*ace 22 c++ stl list vector

我有一个C++程序,它使用包含类实例的std :: list.如果我调用eg myList.push_back(MyClass(variable));它会经历创建临时变量的过程,然后立即将其复制到向量,然后删除临时变量.这并不像我想要的那么高效,当你需要深层复制时很糟糕.

我希望让我的类的构造函数new有所改进而不必实现复制构造函数只是为了第二次分配我的内存而浪费运行时.我也不必立即从向量/列表中找到类实例,然后手动分配内存(或做一些可怕的事情,比如在复制构造函数本身中分配内存).

有什么方法(我不使用Visual Studio BTW)?

tza*_*man 9

咳咳.为了科学的利益,我制作了一个很小的测试程序来检查编译器是否省略了副本:

#include <iostream>
#include <list>
using namespace std;

class Test
{
public:
  Test() { cout<<"Construct\n"; }
  Test(const Test& other) { cout<<"Copy\n"; }
  Test& operator=(const Test& other) { cout<<"Assign\n"; return (*this); }
};

Test rvo() { return Test(); }
int main()
{
  cout<<"Testing rvo:\n";
  Test t = rvo();
  cout<<"Testing list insert:\n";
  list<Test> l;
  l.push_back(Test());
}
Run Code Online (Sandbox Code Playgroud)

这是我在MSVC++ 2008上的输出:

Testing rvo:
Construct 
Testing list insert:
Construct
Copy

调试和发布版本都是一样的:RVO工作,临时对象传递没有优化.
如果我没有弄错的话,在C++ 0x标准中添加的Rvalue引用旨在解决这个问题.


Pot*_*ter 9

C++ 0x移动构造函数是一个部分解决方法:而不是被调用的复制构造函数,移动构造函数将是.移动构造函数就像复制构造函数,但允许使源参数无效.

C++ 0x添加了另一个功能,它可以完全按照您的要求进行操作:emplace_back.(N3092§23.2.3)您将参数传递给构造函数,然后使用这些参数(by ...和forwarding)调用构造函数,因此不能调用其他构造函数.

对于C++ 03,您唯一的选择是为您的班级添加未初始化的状态.在另一个立即调用的函数中执行实际构造push_back.boost::optional可能会帮助您避免初始化类的成员,但它反过来要求它们是可复制构造的.或者,正如弗雷德所说,用最初空的智能指针完成同样的事情.


Nem*_*vic 5

C++ 0x移动构造函数(可用于VC++ 2010和最近的GNU编译器)正是您正在寻找的.