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)
{}
@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