2013-12-15 71 views
23

这是我的理解,std::vector::emplace_back()的目的是专门到避免调用复制构造函数,而是直接构造对象。为什么复制构造函数在调用std :: vector :: emplace_back()时调用?

考虑下面的代码:

#include <memory> 
#include <vector> 
#include <boost/filesystem.hpp> 

using namespace std; 

struct stuff 
{ 
    unique_ptr<int> dummy_ptr; 
    boost::filesystem::path dummy_path; 
    stuff(unique_ptr<int> && dummy_ptr_, 
      boost::filesystem::path const & dummy_path_) 
     : dummy_ptr(std::move(dummy_ptr_)) 
     , dummy_path(dummy_path_) 
    {} 
}; 

int main(int argc, const char * argv[]) 
{ 

    vector<stuff> myvec; 

    // Do not pass an object of type "stuff" to the "emplace_back()" function. 
    // ... Instead, pass **arguments** that would be passed 
    // ... to "stuff"'s constructor, 
    // ... and expect the "stuff" object to be constructed directly in-place, 
    // ... using the constructor that takes those arguments 
    myvec.emplace_back(unique_ptr<int>(new int(12)), boost::filesystem::path()); 

} 

出于某种原因,尽管使用了emplace_back()功能,这段代码编译失败,出现错误:

error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>' [...] This diagnostic occurred in the compiler generated function 'stuff::stuff(const stuff &)'

注意编译器试图创建(并使用)COPY CONSTRUCTOR。正如我上面所讨论的,我的理解是的用途emplace_back()避免复制构造函数的使用。

当然,因为编译器正在尝试创建并调用副本构造,没有办法的代码将编译即使我定义为stuff拷贝构造函数,因为std::unique_ptr不能在副本中使用构造函数。因此,我非常想避免使用复制构造函数(事实上,我需要避免它)。

(这是VS 11.0.60610.01更新3在Windows 7 64位)

为什么编译器生成,并尝试使用,拷贝构造函数,即使我打电话emplace_back()


注(响应@ Yakk的答案):

明确加入移动构造函数,如下所示,可以解决该问题:

stuff(stuff && rhs) 
    : dummy_ptr(std::move(rhs.dummy_ptr)) 
    , dummy_path(rhs.dummy_path) 
{} 

回答

19

的Visual Studio 2013和更早版本无法写入默认为你移动构造函数。添加一个简单的显式移动构造函数到stuff

如果需要重新分配内容,推送或放回内容可能会导致内容被移动,因此您的内容会复制,因为stuff没有任何移动。

这是一个msvc错误。

+2

@dannissenbaum注意移动/复制不是在你的情况下调用,但必须存在的情况下,已经存在的内容在'vector'中,它需要调整大小。该方法的complie时间实例并不知道它在空的'vector'上被调用,所以它必须处理所有的代码路径。 – Yakk

相关问题