2013-12-15 17 views
23

Rozumiem, że celem std::vector::emplace_back() jest specjalnie unikanie wywoływania konstruktora kopii, a zamiast tego konstruowanie obiektu bezpośrednio.Dlaczego konstruktor kopiowania wywoływany w wywołaniu std :: vector :: emplace_back()?

Rozważmy następujący kod:

#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()); 

} 

z jakiegoś powodu, mimo użycia funkcji emplace_back(), ten kod nie skompilować, z błędem:

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 &)'

Zauważmy, że kompilator próbował utworzyć (i użyć) COPY CONSTRUCTOR. Jak już omówiłem powyżej, rozumiem, że celem jest uniknięcie użycia konstruktora kopiowania.

Oczywiście, ponieważ kompilator stara się tworzyć i wywołać konstruktor kopia, nie ma sposobu, kod będzie kompilować nawet jeśli I zdefiniowanego konstruktora kopii dla stuff, ponieważ std::unique_ptr nie mogą być wykorzystane w kopii konstruktor. Dlatego bardzo chciałbym uniknąć użycia konstruktora kopii (w rzeczywistości muszę tego uniknąć).

(To jest VS 11.0.60610.01 Update 3 na Windows 7 64-bit)

Dlaczego kompilator generujący i próbuje użyć, konstruktora kopii, chociaż Wołam emplace_back()?


Note (w odpowiedzi na @ odpowiedź Yakk za):

Jawne dodanie konstruktora poruszać, jak następuje, rozwiązuje problem:

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

Odpowiedz

19

Visual Studio 2013 i wcześniej nie pisać domyślny przenieś konstruktorów dla ciebie. Dodaj prosty konstruktor ruchu do stuff.

Powrót lub emisja może spowodować przeniesienie przesyłki, która musi zostać przeniesiona, co w Twoim przypadku jest kopiowane, ponieważ stuff nie ma żadnego ruchu.

To jest błąd msvc.

+2

@dannissenbaum zauważ, że przenoszenie/kopiowanie nie jest wywoływane w twoim przypadku, ale musi istnieć dla przypadku, w którym istniała już zawartość w 'wektorze' i wymagało zmiany rozmiaru. Instancja czasu zachowania metody nie wie, że jest wywoływana na pustym "wektorze", więc musi obsługiwać wszystkie ścieżki kodu. – Yakk

Powiązane problemy