我将对象的std::unique_ptr
向量A
作为参数传递给对象Obj
的构造函数。当我使用std::move
语法时,这是可行的,如下所示。但是,如果我将另一个对象添加到构造函数的参数列表(下面代码中的mpq_class i
)中,则会得到一个错误消息,该消息将读取
error: call to implicitly-deleted copy constructor of 'std::__1::unique_ptr<A, std::__1::default_delete<A> >'
在OS和
error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Interface; _Dp = std::default_delete<Interface>]’
在linux系统上。
在函数getVector()
中,创建unique_ptr
向量,然后传递给Obj
构造函数,并将对象添加到另一个向量并返回。
我的问题是,如果我为unique_ptrs使用std::move
,为什么代码试图调用一个复制构造函数,以及如何消除它!
生成错误的代码如下所示。
// g++ -Wall -O3 -std=c++1y -lgmpxx -lgmp
#include <vector>
#include <gmpxx.h>
#include <gmp.h>
#include <memory>
#include <iostream>
class A {
public:
A( int y ) : x(y) {}
int x;
};
class Obj {
public:
Obj( mpq_class i, std::vector<std::unique_ptr<A> > v ) : number(i), cont( std::move(v) ) {}
mpq_class number;
std::vector<std::unique_ptr<A> > cont;
};
std::vector<Obj> getVector()
{
std::vector<Obj> result;
int M = 3, N = 5;
for( int mm = 0; mm < M; mm++ )
{
mpq_class rational;
std::vector<std::unique_ptr<A> > abstractObjectsForConstructor;
for(int nn = 0; nn < N; nn++ )
{
mpq_class r(mm,nn);
rational = r;
abstractObjectsForConstructor.push_back( std::make_unique<A>(nn) );
}
result.emplace_back( rational, std::move(abstractObjectsForConstructor) );
}
return result;
}
int main()
{
std::vector<Obj> vec = getVector();
for( unsigned int ii = 0; ii < vec.size(); ii++ )
{
for( unsigned int jj = 0; jj < vec[ii].cont.size(); jj++ )
{
std::cout << vec[ii].cont[jj]->x << '\t' << std::endl;
}
}
return 0;
}
整个错误消息如下:
In file included from vector_unique.cpp:2:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:265:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__bit_reference:15:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:628:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1645:31: error:
call to implicitly-deleted copy constructor of 'std::__1::unique_ptr<A, std::__1::default_delete<A> >'
::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1572:18: note:
in instantiation of function template specialization 'std::__1::allocator<std::__1::unique_ptr<A,
std::__1::default_delete<A> > >::construct<std::__1::unique_ptr<A, std::__1::default_delete<A> >,
std::__1::unique_ptr<A, std::__1::default_delete<A> > &>' requested here
{__a.construct(__p, _VSTD::forward<_Args>(__args)...);}
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1453:14: note:
in instantiation of function template specialization
'std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<A, std::__1::default_delete<A> > >
>::__construct<std::__1::unique_ptr<A, std::__1::default_delete<A> >, std::__1::unique_ptr<A,
std::__1::default_delete<A> > &>' requested here
{__construct(__has_construct<allocator_type, pointer, _Args...>(),
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:1005:25: note:
in instantiation of function template specialization
'std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<A, std::__1::default_delete<A> > >
>::construct<std::__1::unique_ptr<A, std::__1::default_delete<A> >, std::__1::unique_ptr<A,
std::__1::default_delete<A> > &>' requested here
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_), *__first);
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:1203:9: note:
in instantiation of function template specialization 'std::__1::vector<std::__1::unique_ptr<A,
std::__1::default_delete<A> >, std::__1::allocator<std::__1::unique_ptr<A, std::__1::default_delete<A> > >
>::__construct_at_end<std::__1::unique_ptr<A, std::__1::default_delete<A> > *>' requested here
__construct_at_end(__x.__begin_, __x.__end_);
^
vector_unique.cpp:15:8: note: in instantiation of member function 'std::__1::vector<std::__1::unique_ptr<A,
std::__1::default_delete<A> >, std::__1::allocator<std::__1::unique_ptr<A, std::__1::default_delete<A> > >
>::vector' requested here
class Obj {
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1572:18: note:
(skipping 2 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
{__a.construct(__p, _VSTD::forward<_Args>(__args)...);}
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1535:17: note:
in instantiation of function template specialization 'std::__1::allocator_traits<std::__1::allocator<Obj>
>::construct<Obj, const Obj &>' requested here
construct(__a, _VSTD::__to_raw_pointer(__end2-1), _VSTD::move_if_noexcept(*--__end1));
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:874:21: note:
in instantiation of function template specialization 'std::__1::allocator_traits<std::__1::allocator<Obj>
>::__construct_backward<Obj *>' requested here
__alloc_traits::__construct_backward(this->__alloc(), this->__begin_, this->__end_, __v.__begin_);
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:1621:5: note:
in instantiation of member function 'std::__1::vector<Obj, std::__1::allocator<Obj>
>::__swap_out_circular_buffer' requested here
__swap_out_circular_buffer(__v);
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:1639:9: note:
in instantiation of function template specialization 'std::__1::vector<Obj, std::__1::allocator<Obj>
>::__emplace_back_slow_path<__gmp_expr<mpq_t, mpq_t> &, std::__1::vector<std::__1::unique_ptr<A,
std::__1::default_delete<A> >, std::__1::allocator<std::__1::unique_ptr<A, std::__1::default_delete<A> > > > >'
requested here
__emplace_back_slow_path(_VSTD::forward<_Args>(__args)...);
^
vector_unique.cpp:40:11: note: in instantiation of function template specialization 'std::__1::vector<Obj,
std::__1::allocator<Obj> >::emplace_back<__gmp_expr<mpq_t, mpq_t> &, std::__1::vector<std::__1::unique_ptr<A,
std::__1::default_delete<A> >, std::__1::allocator<std::__1::unique_ptr<A, std::__1::default_delete<A> > > > >'
requested here
result.emplace_back( rational, std::move(abstractObjectsForConstructor) );
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:2515:31: note:
copy constructor is implicitly deleted because 'unique_ptr<A, std::__1::default_delete<A> >' has a
user-declared move constructor
_LIBCPP_INLINE_VISIBILITY unique_ptr(unique_ptr&& __u) _NOEXCEPT
^
1 error generated.
发布于 2015-07-15 13:34:05
罪魁祸首是mpq_class
。使用简单的虚拟版本,它编译得很好(我注释掉了gmp的标头):
struct mpq_class {
mpq_class() {}
mpq_class( int, int );
};
然而,当你使这类课程不可移动时:
struct mpq_class {
mpq_class() {}
mpq_class( int, int );
mpq_class( const mpq_class & ) {}
mpq_class( mpq_class && ) = delete;
mpq_class &operator=( const mpq_class & ) {return *this;}
};
你的问题回来了。
因此,如果mpq_class
不是可移动的,那么Obj
也不能移动,emplace_back
的使用会隐式地生成代码,在重新定位的情况下复制Obj
,因为std::unique_ptr<A>
是不可复制的,所以无法编译。
发布于 2015-07-15 13:22:32
错,见下文
问题在于Obj构造函数的定义。它的第二个参数是通过值传递的,这将导致复制。在初始化程序列表中使用std::move并不会改变这一事实。
补救方法是对Obj构造函数的第二个参数使用rvalue引用。
https://stackoverflow.com/questions/31431057
复制相似问题