2013-12-15 6 views
23

Es ist mein Verständnis, dass der Zweck std::vector::emplace_back() speziell auf vermeiden ist eine Kopie Konstruktor aufrufen und stattdessen das Objekt direkt zu konstruieren.Warum Copykonstruktor wird in Aufruf aufgerufen std :: vector :: emplace_back()?

den folgenden Code vor:

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

} 

Aus irgendeinem Grund, trotz der Verwendung der emplace_back() Funktion schlägt fehl, diesen Code zu kompilieren, mit dem Fehler:

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

Beachten Sie, dass der Compiler versucht, die Copykonstruktor zu erstellen (und benutzen). Wie ich oben beschrieben habe, ist es mein Verständnis, dass der Zweck von emplace_back()-vermeiden ist die Verwendung des Copy-Konstruktor.

Natürlich, da der Compiler die Kopie Konstruktor zu erstellen und rufen versucht, gibt es keine Möglichkeit, den Code kompilieren würde selbst wenn ich den Kopierkonstruktor definiert für stuff, weil die std::unique_ptr nicht in einer Kopie verwendet werden kann, Konstrukteur. Daher würde ich sehr gerne die Verwendung eines Kopierkonstruktors vermeiden (tatsächlich muss ich es vermeiden).

(Dies ist VS 11.0.60610.01 Update 3 auf Windows 7 64-Bit)

Warum ist der Compiler Erzeugen, und versucht, die Copykonstruktor zu verwenden, auch wenn ich emplace_back() nenne?


Hinweis (als Antwort auf @ Yakk Antwort):

Explizit den Umzug Konstruktor hinzufügen, wie folgt, löst das Problem:

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

Antwort

19

Visual Studio 2013 und früher nicht standardmäßig schreiben Konstruktoren für Sie verschieben. Fügen Sie einen einfachen expliziten Verschiebungskonstruktor zu stuff hinzu.

Ein Push- oder Zurücksetzen kann dazu führen, dass Objekte verschoben werden, wenn sie neu zugeordnet werden müssen, was in Ihrem Fall kopiert wird, da stuff keine Verschiebung aufweist.

Es ist ein msvc Fehler.

+2

@dannissenbaum beachten Sie, dass das Verschieben/Kopieren nicht in Ihrem Fall aufgerufen wird, muss aber für den Fall existieren, wo es bereits Inhalt in dem 'VECTOR' vorlag, wurde es erforderlich, um die Größe. Die Comple-Zeitinstanz der Methode weiß nicht, dass sie auf einem leeren "Vektor" aufgerufen wird, so dass sie alle Codepfade behandeln muss. – Yakk

Verwandte Themen