It is my understanding that the purpose of std::vector::emplace_back()
is specifically to avoid calling a copy constructor, and instead to construct the object directly.
Consider the following code:
#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());
}
For some reason, despite the use of the emplace_back()
function, this code fails to compile, with the error:
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 &)'
Notice that the compiler attempted to create (and use) the COPY CONSTRUCTOR . As I've discussed above, it's my understanding that the purpose of emplace_back()
is to avoid the use of the copy constructor.
Of course, since the compiler is attempting to create and call the copy constructor, there's no way the code would compile even if I defined the copy constructor for stuff
, because the std::unique_ptr
cannot be used in a copy constructor. Hence, I would very much like to avoid the use of a copy constructor (in fact, I need to avoid it).
(This is VS 11.0.60610.01 Update 3 on Windows 7 64-bit)
Why is the compiler generating, and attempting to use, the copy constructor, even though I am calling emplace_back()
?
Note (in response to @Yakk's answer):
Explicitly adding the move constructor, as follows, resolves the problem:
stuff(stuff && rhs)
: dummy_ptr(std::move(rhs.dummy_ptr))
, dummy_path(rhs.dummy_path)
{}
Visual Studio 2013 and earlier fails to write default move constructors for you. Add a simple explicit move constructor to stuff
.
A push or emplace back can cause stuff to be moved if it needs to reallocate, which in your case copies, as stuff
has no move.
It is a msvc bug.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.