Zee*_*bit 26 c++ rvalue-reference move-constructor move-semantics c++11
我一直在探索C++ 中Move Constructors的可能性,我想知道在下面的例子中有哪些方法可以利用这个功能.考虑以下代码:
template<unsigned int N>
class Foo {
public:
    Foo() {
        for (int i = 0; i < N; ++i) _nums[i] = 0;
    }
    Foo(const Foo<N>& other) {
        for (int i = 0; i < N; ++i) _nums[i] = other._nums[i];
    }
    Foo(Foo<N>&& other) {
        // ??? How can we take advantage of move constructors here?
    }
    // ... other methods and members
    virtual ~Foo() { /* no action required */ }
private:
    int _nums[N];
};
Foo<5> bar() {
    Foo<5> result;
    // Do stuff with 'result'
    return result;
}
int main() {
    Foo<5> foo(bar());
    // ...
    return 0;
}
在上面的例子中,如果我们跟踪程序(使用MSVC++ 2011),我们会看到Foo<N>::Foo(Foo<N>&&)在构造时调用foo它,这是所需的行为.但是,如果我们没有Foo<N>::Foo(Foo<N>&&),Foo<N>::Foo(const Foo<N>&)则会调用,这将执行冗余复制操作.
我的问题是,如代码中所述,使用静态分配的简单数组的这个特定示例,有没有办法利用移动构造函数来避免这个冗余副本?
Ker*_* SB 22
首先,有建议的总体排序,说你不应该写任何拷贝/移动构造函数,赋值运算符或析构函数在所有如果你能帮助它,而撰写您一流的高品质组件又提供了这些的,允许默认生成的函数执行正确的操作.(反过来说,如果你必须写任何一个,你可能必须写所有这些.)
所以问题归结为"哪个单一责任组件类可以利用移动语义?" 一般的答案是:管理资源的任何东西.关键是移动构造函数/分配器只是将资源重新安装到新对象并使旧对象无效,从而避免(假定的昂贵或不可能的)新分配和资源的深度复制.
主要的例子是管理动态内存的任何东西,其中移动操作只是复制指针并将旧对象的指针设置为零(因此旧对象的析构函数不执行任何操作).这是一个天真的例子:
class MySpace
{
  void * addr;
  std::size_t len;
public:
  explicit MySpace(std::size_t n) : addr(::operator new(n)), len(n) { }
  ~MySpace() { ::operator delete(addr); }
  MySpace(const MySpace & rhs) : addr(::operator new(rhs.len)), len(rhs.len)
  { /* copy memory */ }
  MySpace(MySpace && rhs) : addr(rhs.addr), len(rhs.len)
  { rhs.len = 0; rhs.addr = 0; }
  // ditto for assignment
};
关键是任何复制/移动构造函数都会对成员变量进行完全复制; 只有当这些变量本身是句柄或指向资源的指针时才能避免复制资源,因为一致认为移动的对象不再被认为是有效的,并且您可以自由地从中窃取它.如果没有什么可偷的,那么移动就没有任何好处.
在这种情况下,它没有用,因为int没有move-constructors.
但是,如果它们是字符串,则可能很有用,例如:
template<unsigned int N>
class Foo {
public:
    // [snip]
    Foo(Foo<N>&& other) {
        // move each element from other._nums to _nums
        std::move(std::begin(other._nums), std::end(other._nums), &_nums[0]);
    }
    // [snip]
private:
    std::string _nums[N];
};
现在,您可以避免复制移动所在的字符串.如果完全省略所有复制/移动构造函数,我不确定符合要求的C++ 11编译器是否会生成等效代码,抱歉.
(换句话说,我不确定是否std::move特别定义了为数组做元素移动.)