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...
}
这样做,您将在可能的情况下获得无例外:

注意到VisualStudio 2015和更老版本的早期版本不支持,即使它支持移动语义。

< 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

我想这也是答案。

有趣的是,如果移动构造函数和析构函数都是
noexcept
,GCC4.7.2的向量只使用移动构造函数。一个简单的例子:

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;   
};

似乎(对于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”。您可以,通过使用移动感知向量实现。您能否更具体地说明如何实现这一点?您只需使用移动感知向量实现即可。听起来您的标准库实现(顺便说一句,是哪个?)不支持移动。您可以尝试使用Boost中的移动感知容器。我使用gcc 4.5.1,它是移动感知的。在我的代码中,它使复制构造函数成为私有的,尽管移动构造函数没有显式的“noexcept”。在我看来,其他答案只讨论移动构造函数,不是说析构函数必须是noexcept。好吧,它应该是,但事实证明,在GCC4.7.2中它不是。所以这个问题实际上是gcc特有的。不过,它应该在GCC4.8.0中得到修复。看。在我看来,其他答案只讨论了移动构造函数,而不是析构函数必须是noexcept。好吧,它应该是,但事实证明,在gcc 4.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()
。当你努力寻找一个问题,却看不到眼前明显的错误的时候。然后是午餐时间,我忘了删除我的评论。出于兴趣,impl如何“知道”
value\u type
的move-ctor是否为
n