C++ 当向量增长时,如何强制执行移动语义?
我有一个特定类的对象的C++ 当向量增长时,如何强制执行移动语义?,c++,vector,c++11,resize,move-semantics,C++,Vector,C++11,Resize,Move Semantics,我有一个特定类的对象的std::vector。该类是非平凡的,并且定义了复制构造函数和移动构造函数 std::vector<A> myvec; std::vector myvec; 如果我用A对象填充向量(例如使用myvec.push_back(A)),向量将增大,使用复制构造函数A(const A&)实例化向量中元素的新副本 我能不能强制执行类移动< < />代码>?开始使用?< p>您需要通知移动构造函数和析构函数不抛出的C++(具体是代码> STD::vector < /
std::vector
。该类是非平凡的,并且定义了复制构造函数和移动构造函数
std::vector<A> myvec;
std::vector myvec;
如果我用A
对象填充向量(例如使用myvec.push_back(A)
),向量将增大,使用复制构造函数A(const A&)
实例化向量中元素的新副本
我能不能强制执行类<代码>移动< < />代码>?开始使用?
< p>您需要通知移动构造函数和析构函数不抛出的C++(具体是代码> STD::vector < /代码>),使用<代码> NO>除< /代码>之外。然后,当向量增长时,将调用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...
}
这样做,您将在可能的情况下获得无例外:
请注意,Visual Studio 2015及更高版本的早期版本不支持此功能,即使它支持移动语义。有趣的是,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();
}
但是,当我从~foo()
中删除noexcept
时,结果不同:
copy
copy
copy
我想这也是答案。似乎,唯一的方法(对于C++17和早期版本)是在重新分配时强制执行
std::vector
使用移动语义,即删除复制构造函数:)。通过这种方式,它将使用您的移动构造函数或在编译时尝试:)
在许多规则中,std::vector
不得在重新分配时使用移动构造函数,但没有任何关于必须在哪里使用它的规则
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;
};
你可以,通过使用移动感知向量实现。你能更具体一点如何实现吗?你只需要使用移动感知向量实现。听起来您的标准库实现(顺便说一句,是哪个?)不支持移动。您可以尝试使用Boost中的移动感知容器。我使用gcc 4.5.1,它是移动感知的。在我的代码中,它使复制构造函数成为私有的,尽管移动构造函数没有显式的“noexcept”。在我看来,其他答案只讨论移动构造函数,不是说析构函数必须是noexcept。好吧,它应该是,但事实证明,在GCC4.7.2中它不是。所以这个问题实际上是gcc特有的。不过,它应该在GCC4.8.0中得到修复。请参见。出于兴趣,impl如何“知道”值类型的move-ctor是否为
noexcept
?当调用范围也是一个noexcept
函数时,语言可能会限制函数调用候选集?@LightnessRacesinOrbit我认为它只是在执行以下操作。只能有一个移动构造函数,因此应该由声明明确定义。@LightnessRacesinOrbit,我了解到没有(标准/有用的)方法真正知道是否存在noexcept
move构造函数<如果存在nothrow
copy构造函数,则code>is\u nothrow\u move\u constructible将为真。我不知道任何昂贵的nothrow
copy构造函数的真实案例,所以不清楚它是否真的重要。对我来说不起作用。我的析构函数、移动构造函数和移动分配函数在头和实现中都标记为noexcept
,当我执行push_-back(std:;move)时,它仍然调用复制构造函数。“我在这儿胡闹。”约翰,我发现了问题所在。我在错误的push\u back()
调用中使用了std::move()
。当你努力寻找一个问题,却看不到眼前明显的错误的时候。然后是午餐时间,我忘了删除我的评论。没有必要删除复制构造函数。如果move构造函数是noexcept,则将使用它。@balki可以使用它。标准现在不需要这样做。这里是讨论
copy
copy
copy
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 {};
};
std::vector<move_only<MyClass>> vec;