为了账号安全,请及时绑定邮箱和手机立即绑定

向量增长时如何执行移动语义?

向量增长时如何执行移动语义?

C++
一只斗牛犬 2019-06-21 12:31:10
向量增长时如何执行移动语义?我有一个std::vector某一类物体的A..该类具有非平凡性,并具有副本构造函数。和定义移动构造函数。std::vector<A>  myvec;如果我用A对象(使用例如:myvec.push_back(a)),使用复制构造函数,向量的大小将增加。A( const A&)实例化向量中元素的新副本。我能以某种方式强制执行类的移动构造函数吗?A是不是用了?
查看完整描述

3 回答

?
慕容3067478

TA贡献1773条经验 获得超3个赞

您需要通知C+(特别是std::vector)移动构造函数和析构函数不会引发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...
}

如果构造函数不是noexceptstd::vector不能使用它,因为它不能保证标准所要求的异常保证。

有关标准中所述内容的更多信息,请阅读C+移动语义和异常

这归功于薄,他暗示这可能与例外有关。还可以考虑克雷克的建议和使用emplace_back如果可能的话。它能,会,可以更快(但通常不是),它可以更清晰和更紧凑,但也有一些缺陷(特别是对非显式构造函数)。

编辑通常默认情况是您想要的:移动所有可以移动的东西,复制其余的。要明确地要求这样做,请写

A(A && rhs) = default;

这样做,你会得到不,除非有可能:默认的移动构造函数是否定义为no以外?

请注意,VisualStudio 2015及更高版本的早期版本不支持这一点,尽管它支持移动语义。


查看完整回答
反对 回复 2019-06-21
?
Cats萌萌

TA贡献1805条经验 获得超9个赞

有趣的是,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

我想这也是这个问题.


查看完整回答
反对 回复 2019-06-21
?
慕勒3428872

TA贡献1848条经验 获得超6个赞

似乎,(对于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;   
};

生活,居住

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;


查看完整回答
反对 回复 2019-06-21
  • 3 回答
  • 0 关注
  • 468 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信