[英]vector<unique_ptr<A> > in constructor - error: call to implicitly-deleted copy constructor
I am passing a vector of std::unique_ptr
of objects A
as a parameter to a constructor of objects Obj
. 我将对象
A
的std::unique_ptr
向量作为参数传递给对象Obj
的构造函数。 This is working when I use the std::move
syntax as is shown below. 当使用如下所示的
std::move
语法时,此方法有效。 However, if I add another object to the constructor's parameter list (the mpq_class i
in the below code) I get an error message that reads 但是,如果将另一个对象添加到构造函数的参数列表中(以下代码中的
mpq_class i
, mpq_class i
收到一条错误消息 ,内容为:
error: call to implicitly-deleted copy constructor of 'std::__1::unique_ptr<A, std::__1::default_delete<A> >'
on OS X and 在OS X和
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>]’
on a linux system. 在linux系统上。
In the function getVector()
the vector of unique_ptr
is created, then passed to the Obj
constructor and the objects are added to another vector and returned. 在函数
getVector()
,创建unique_ptr
的向量,然后将其传递给Obj
构造函数,然后将对象添加到另一个向量中并返回。
My question is why the code tries to call a copy constructor if I use std::move
for the unique_ptrs and how to get rid of it! 我的问题是,如果我将
std::move
用作unique_ptrs,为什么代码会尝试调用副本构造函数,以及如何摆脱它!
The code that produces the error is shown below. 产生错误的代码如下所示。
// 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;
}
The whole error message reads: 整个错误消息显示为:
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.
Culprit is mpq_class
. mpq_class
是mpq_class
。 With simple dummy version it compiles fine (I commented out headers for gmp) : 使用简单的虚拟版本,它可以很好地编译(我注释掉了gmp的标头):
struct mpq_class {
mpq_class() {}
mpq_class( int, int );
};
However, when you make that class not movable: 但是,当您使该类不可移动时:
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;}
};
Your problem comes back. 您的问题又回来了。
So issue that if mpq_class
is not movable then Obj
is not movable either and usage of emplace_back
implicitly generates code to copy Obj
in case of relocation which fails to compile because std::unique_ptr<A>
is not copyable. 因此,如果
mpq_class
不可移动,则Obj
也不可移动,并且如果mpq_class
std::unique_ptr<A>
无法复制,则在无法编译的重定位情况下, emplace_back
使用emplace_back
隐式生成用于复制Obj
代码。
[wrong, see below] [错误,请参阅下文]
The problem is with the definition of the Obj constructor. 问题在于Obj构造函数的定义。 Its second argument is passed by value, which results in a copy being made.
它的第二个参数按值传递,这将导致复制。 The fact that you use std::move in the initializer list does not change this fact.
您在初始化列表中使用std :: move的事实不会更改此事实。
The remedy is to use an rvalue reference for the second argument of the Obj constructor. 补救措施是为Obj构造函数的第二个参数使用右值引用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.