标签: move-constructor

vector :: push_back坚持使用复制构造函数,但提供了移动构造函数

我从gcc收到一个奇怪的错误,无法弄清楚原因.我制作了以下示例代码,以使问题更加清晰.基本上,有一个类定义,我为其复制构造函数和复制赋值运算符私有,以防止意外调用它们.

#include <vector>
#include <cstdio>
using std::vector;

class branch 
{
public:
  int th;

private:
  branch( const branch& other );
  const branch& operator=( const branch& other );

public:

  branch() : th(0) {}

  branch( branch&& other )
  {
    printf( "called! other.th=%d\n", other.th );
  }

  const branch& operator=( branch&& other )
  {
    printf( "called! other.th=%d\n", other.th );
    return (*this);
  }

};



int main()
{
  vector<branch> v;
  branch a;
  v.push_back( std::move(a) );

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我希望这段代码能够编译,但是gcc失败了.实际上gcc抱怨"branch :: branch(const branch&)是私有的",据我所知,不应该调用它.

赋值运算符可以工作,因为如果我用main替​​换main()的主体

branch a;
branch b; …
Run Code Online (Sandbox Code Playgroud)

c++ gcc move-constructor c++11

17
推荐指数
2
解决办法
5347
查看次数

通过调用移动赋值运算符实现移动构造函数

MSDN文章如何:编写移动构造函数具有以下建议.

如果为类提供移动构造函数和移动赋值运算符,则可以通过编写移动构造函数来调用移动赋值运算符来消除冗余代码.以下示例显示了调用移动赋值运算符的移动构造函数的修订版本:

// Move constructor.
MemoryBlock(MemoryBlock&& other)
   : _data(NULL)
   , _length(0)
{
   *this = std::move(other);
}
Run Code Online (Sandbox Code Playgroud)

这个代码是通过双重初始化MemoryBlock的值来实现低效的,还是编译器能够优化掉额外的初始化?我是否应该通过调用移动赋值运算符来编写移动构造函数?

c++ move-constructor move-semantics c++11

17
推荐指数
2
解决办法
8994
查看次数

如何检查是否隐式生成移动构造函数?

我有几个类,我想检查是否正在生成默认的移动构造函数.有没有办法检查这个(无论是编译时断言,还是解析生成的目标文件,还是别的东西)?


励志示例:

class MyStruct : public ComplicatedBaseClass {
    std::vector<std::string> foo; // possibly huge
    ComplicatedSubObject bar;
};
Run Code Online (Sandbox Code Playgroud)

如果任何类的任何基Complicated...Object类或成员的任何成员都不能被移动,MyStruct则不会生成其隐式移动构造函数,并且因此可能无法优化复制foo工作,即使foo可移动也可以进行移动.


我希望避免:

  1. 繁琐地检查隐式移动ctor生成的条件,
  2. 显式地和递归地默认所有受影响的类,它们的基础和它们的成员的特殊成员函数 - 只是为了确保移动构造函数可用.

我已经尝试过以下内容但它们不起作用:

  1. std::move明确使用- 如果没有可用的移动ctor,这将调用复制ctor.
  2. 使用std::is_move_constructible-this将在复制构造函数接受时成功const Type&,默认情况下生成(只要移动构造函数未被显式删除,至少).
  3. 使用nm -C以检查移动构造函数的存在[见下文].但是,另一种方法是可行的[见答案].

我试着看一下像这样的普通类的生成符号:

#include <utility>

struct MyStruct {
    MyStruct(int x) : x(x) {}
    //MyStruct(const MyStruct& rhs) : x(rhs.x) {}
    //MyStruct(MyStruct&& rhs) : x(rhs.x) {}
    int x;
};

int main() {
    MyStruct s1(4); …
Run Code Online (Sandbox Code Playgroud)

c++ move-constructor c++11

17
推荐指数
2
解决办法
3783
查看次数

移动构造函数和多重继承

概要

当类使用多重继承时,如何安全地设计移动构造函数?

细节

请考虑以下情形:

struct T { };
struct U { };

struct X : public T, public U
{
    X(X&& other)
      : T(std::move(other))
      , U(std::move(other)) // already moved?!
    {
    }
};
Run Code Online (Sandbox Code Playgroud)

有没有办法移动 - 构建TU安全?

c++ multiple-inheritance move-constructor move-semantics c++11

15
推荐指数
1
解决办法
1826
查看次数

移动构造函数和继承

我试图理解移动构造函数和赋值操作在C++ 11中的工作方式,但是我遇到了委托父类的问题.

代码:

class T0
{
public:
    T0() { puts("ctor 0"); }
    ~T0() { puts("dtor 0"); }
    T0(T0 const&) { puts("copy 0"); }
    T0(T0&&) { puts("move 0"); }
    T0& operator=(T0 const&) { puts("assign 0"); return *this; }
    T0& operator=(T0&&) { puts("move assign 0"); return *this; }
};

class T : public T0
{
public:
    T(): T0() { puts("ctor"); }
    ~T() { puts("dtor"); }
    T(T const& o): T0(o) { puts("copy"); }
    T(T&& o): T0(o) { puts("move"); }
    T& operator=(T const& o) …
Run Code Online (Sandbox Code Playgroud)

c++ visual-c++ move-constructor c++11 visual-studio-2012

15
推荐指数
2
解决办法
9217
查看次数

什么是C++中的复制/移动构造函数选择规则?什么时候发生移动复制后备?

第一个例子:

#include <iostream>
#include <memory>
using namespace std;

struct A {
    unique_ptr<int> ref;
    A(const A&) = delete;
    A(A&&) = default;
    A(const int i) : ref(new int(i)) { }
    ~A() = default;
};

int main()
{
    A a[2] = { 0, 1 };
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

它完美地运作.所以这里使用了MOVE构造函数.

让我们删除移动构造函数并添加一个副本:

#include <iostream>
#include <memory>
using namespace std;

struct A {
    unique_ptr<int> ref;
    A(const A&a) 
        : ref( a.ref.get() ? new int(*a.ref) : nullptr )
    {  }
    A(A&&) = delete;
    A(const int i) : ref(new …
Run Code Online (Sandbox Code Playgroud)

c++ copy-constructor move-constructor c++11

15
推荐指数
2
解决办法
1008
查看次数

移动构造函数调用基类Move Constructor

我有一个基类,它基本上将一个类附加到任意窗口句柄(例如,HWND,HFONT),并使用策略类来附加/分离和销毁:

// class SmartHandle
template<typename THANDLE, class TWRAPPER, class TPOLICY>
class SmartHandle : boost::noncopyable
{
private:
    TPOLICY*  m_pPolicy;    // Policy
    bool m_bIsTemporary;    // Is this a temporary window?

    SmartHandle();  // no default ctor
    SmartHandle(const SmartHandle<THANDLE, TWRAPPER, TPOLICY>&);    // no cctor
protected:
    THANDLE   m_hHandle;    // Handle to the underlying window

    TPOLICY& policy() {return(*m_pPolicy);};

    // ctor that attaches but is temporary
    SmartHandle(const THANDLE& _handle, bool _temporary) : m_hHandle(_handle)
                                                         , m_bIsTemporary(_temporary)
    {
        m_pPolicy = new TPOLICY(reinterpret_cast<TWRAPPER&>(*this));
        if(_handle)
            m_pPolicy->attach(_handle);
    };  // eo ctor

    // …
Run Code Online (Sandbox Code Playgroud)

c++ templates move-constructor c++11

14
推荐指数
3
解决办法
6532
查看次数

为什么我需要在move-constructor的初始化列表中使用std :: move?

假设我有一个(普通的)类,它是可移动构造和可移动分配但不可复制构造或可复制分配:

class movable
{
  public:
    explicit movable(int) {}
    movable(movable&&) {}
    movable& operator=(movable&&) { return *this; }
    movable(const movable&) = delete;
    movable& operator=(const movable&) = delete;
};
Run Code Online (Sandbox Code Playgroud)

这很好用:

movable m1(movable(17));
Run Code Online (Sandbox Code Playgroud)

当然,这不起作用,因为m1它不是右值:

movable m2(m1);
Run Code Online (Sandbox Code Playgroud)

但是,我可以包m1std::move,它投射到一个右值引用,以使其工作:

movable m2(std::move(m1));
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.现在,假设我有一个(同样微不足道的)容器类,它包含一个值:

template <typename T>
class container
{
  public:
    explicit container(T&& value) : value_(value) {}
  private:
    T value_;
};
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用:

container<movable> c(movable(17));
Run Code Online (Sandbox Code Playgroud)

编译器(我试过clang 4.0和g ++ 4.7.2)抱怨我正在尝试movablecontainer初始化列表中使用已删除的复制构造函数.同样,包裹valuestd::move使得它的工作:

    explicit container(T&& value) : value_(std::move(value)) {} …
Run Code Online (Sandbox Code Playgroud)

c++ rvalue-reference move-constructor move-semantics c++11

14
推荐指数
2
解决办法
2600
查看次数

理解`std :: is_move_constructible`

没有移动构造函数但带有接受const T&参数的复制构造函数的类型满足std::is_move_constructible.例如,在以下代码中:

#include <type_traits>

struct T {
    T(const T&) {}
    //T(T&&) = delete;
};

int main() {
    static_assert(std::is_move_constructible<T>::value, "not move constructible");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

T 将没有隐式移动构造函数,因为它具有用户定义的复制构造函数.

但是,如果我们取消注释移动构造函数的显式删除,则代码不再编译.为什么是这样?我原以为显式复制构造函数仍然会满足std::is_move_constructible.

重载是否起作用,选择声明的移动构造函数然后失败,因为它被删除了?


如果a no implicit move ctordeleted move ctorclass 之间的移动构造性之间的差异是由标准规定的,请引用,并且如果可能的话,给出一个基本原理(例如"提供禁止移动构造的设施" - 首先想到的事情).

c++ move-constructor c++11

14
推荐指数
2
解决办法
1794
查看次数

Visual Studio 2017是否需要显式移动构造函数声明?

下面的代码可以使用Visual Studio 2015成功编译,但使用Visual Studio 2017失败.Visual Studio 2017报告:

错误C2280:"std :: pair :: pair(const std :: pair&)":尝试引用已删除的函数

#include <unordered_map>
#include <memory>

struct Node
{
  std::unordered_map<int, std::unique_ptr<int>> map_;
  // Uncommenting the following two lines will pass Visual Studio 2017 compilation
  //Node(Node&& o) = default;
  //Node() = default;
};

int main()
{
  std::vector<Node> vec;
  Node node;
  vec.push_back(std::move(node));
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

看起来Visual Studio 2017显式需要移动构造函数声明.是什么原因?

c++ move-constructor visual-studio-2017

14
推荐指数
3
解决办法
1163
查看次数