2013-12-15 2 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 &)'

Обратите внимание, что компилятор попытался создать (и использовать) КОПИРОВАННЫЙ КОНСТРУКТОР. Как я уже говорил выше, я понимаю, что цель от emplace_back() составляет , избегая использования конструктора копирования.

Конечно, так как компилятор пытается создать и вызвать конструктор копию, нет никакого способа, код компилируется даже если я определил конструктор копирования для stuff, потому что std::unique_ptr не может быть использована в копии конструктор. Следовательно, я очень хотел бы избежать использования конструктора копирования (на самом деле, мне нужно его избегать).

(Это VS 11.0.60610.01 Update 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', поэтому он должен обрабатывать все пути кода. – Yakk

Смежные вопросы