我有std::vector
某类的东西A
。该类很简单,并定义了复制构造函数和 move构造函数。
std::vector<A> myvec;
如果我用A
对象填充矢量(例如使用myvec.push_back(a)
),则矢量的大小将增大,使用复制构造函数A( const A&)
实例化矢量中元素的新副本。
我能以某种方式强制A
使用class的move构造函数代替beging吗?
我有std::vector
某类的东西A
。该类很简单,并定义了复制构造函数和 move构造函数。
std::vector<A> myvec;
如果我用A
对象填充矢量(例如使用myvec.push_back(a)
),则矢量的大小将增大,使用复制构造函数A( const A&)
实例化矢量中元素的新副本。
我能以某种方式强制A
使用class的move构造函数代替beging吗?
Answers:
您需要使用来告知C ++(特别是std::vector
)您的move构造函数和destructor不会抛出noexcept
。然后,当向量增长时,将调用move构造函数。
这是如何声明和实现受以下方面尊重的移动构造函数的方法std::vector
:
A(A && rhs) noexcept {
std::cout << "i am the move constr" <<std::endl;
... some code doing the move ...
m_value=std::move(rhs.m_value) ; // etc...
}
如果构造函数不是noexcept
,std::vector
则不能使用它,因为它不能确保标准所要求的异常保证。
有关标准中所说内容的更多信息,请阅读 C ++ Move语义和异常
感谢Bo暗示它可能与例外有关。还请考虑Kerrek SB的建议并emplace_back
在可能的情况下使用。它可以更快(但通常不是),它可以更清晰,更紧凑,但也存在一些陷阱(尤其是对于非显式构造函数)。
编辑,通常是您想要的默认值:移动所有可以移动的内容,复制其余内容。要明确要求,写
A(A && rhs) = default;
这样,您将在可能的情况下获得noexcept:默认的Move构造函数是否定义为noexcept?
请注意,Visual Studio 2015和更早版本的早期版本不支持该功能,即使它支持移动语义。
value_type
“的举动男星是noexcept
?当调用范围也是noexcept
函数时,语言可能会限制函数调用候选集?
noexcept
移动构造函数。is_nothrow_move_constructible
如果有nothrow
复制构造函数,则为true 。我不知道任何昂贵的nothrow
拷贝构造函数的实际情况,因此尚不清楚它是否真正重要。
noexcept
在标头和实现中都标记了,当我执行push_back(std:; move)时,它仍会调用复制构造函数。我在这里扯头发。
std::move()
打错了push_back()
电话。在那些情况下,您非常努力地寻找问题,以至于看不到眼前的明显错误。然后是午餐时间,我忘了删除我的评论。
有趣的是,如果移动构造函数和析构函数均为,则gcc 4.7.2的向量仅使用移动构造函数noexcept
。一个简单的例子:
struct foo {
foo() {}
foo( const foo & ) noexcept { std::cout << "copy\n"; }
foo( foo && ) noexcept { std::cout << "move\n"; }
~foo() noexcept {}
};
int main() {
std::vector< foo > v;
for ( int i = 0; i < 3; ++i ) v.emplace_back();
}
这将输出预期的:
move
move
move
但是,当我noexcept
从中删除时~foo()
,结果是不同的:
copy
copy
copy
我猜这也回答了这个问题。
看来,std::vector
在重新分配时强制使用move move语义的唯一方法(对于C ++ 17和早期版本)是删除复制构造函数:)。这样,它将在编译时使用您的move构造函数或进行尝试:)。
在很多规则中,std::vector
不得在重新分配时使用move构造函数,但在任何地方都不得使用它。
template<class T>
class move_only : public T{
public:
move_only(){}
move_only(const move_only&) = delete;
move_only(move_only&&) noexcept {};
~move_only() noexcept {};
using T::T;
};
要么
template<class T>
struct move_only{
T value;
template<class Arg, class ...Args, typename = std::enable_if_t<
!std::is_same_v<move_only<T>&&, Arg >
&& !std::is_same_v<const move_only<T>&, Arg >
>>
move_only(Arg&& arg, Args&&... args)
:value(std::forward<Arg>(arg), std::forward<Args>(args)...)
{}
move_only(){}
move_only(const move_only&) = delete;
move_only(move_only&& other) noexcept : value(std::move(other.value)) {};
~move_only() noexcept {};
};
您的T
班级必须具有noexcept
移动构造函数/辅助运算符和noexcept
析构函数。否则会出现编译错误。
std::vector<move_only<MyClass>> vec;