移动构造函数和静态数组 [英] Move Constructors and Static Arrays

查看:133
本文介绍了移动构造函数和静态数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在探索在C ++中移动构造函数的可能性,我想知道在下面的示例中利用该特征的一些方式是什么。考虑这个代码:

I've been exploring the possibilities of Move Constructors in C++, and I was wondering what are some ways of taking advantage of this feature in an example such as below. Consider this code:

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 Foo :: Foo(Foo & amp;) >,这是所需的行为。然而,如果我们没有 Foo :: Foo(Foo &&) Foo< N> ;: :

In this above example, if we trace the program (with MSVC++ 2011), we see that Foo<N>::Foo(Foo<N>&&) is called when constructing foo, which is the desired behaviour. However, if we didn't have Foo<N>::Foo(Foo<N>&&), Foo<N>::Foo(const Foo<N>&) would be called instead, which would do a redundant copy operation.

我的问题是,你可以使用Foo(const Foo< N>&)如代码中所示,对于使用静态分配的简单数组的具体示例,有没有办法利用move构造函数来避免这种冗余副本?

My question is, as noted in the code, with this specific example which is using a statically-allocated simple array, is there any way to utilize the move constructor to avoid this redundant copy?

推荐答案

首先,有一个一般的建议,说你不应该写任何复制/移动构造函数,赋值运算符或析构函数,如果你可以帮助它,而是撰写您的类别的高品质组件,反过来提供这些,允许默认生成的功能做正确的事。 (相反的含义是,如果你必须写任何一个,你可能必须写所有的。)

First off, there's a general sort of advice that says you shouldn't write any copy/move constructor, assignment operator or destructor at all if you can help it, and rather compose your class of high-quality components which in turn provide these, allowing the default-generated functions to Do The Right Thing. (The reverse implication is that if you do have to write any one of those, you probably have to write all of them.)

所以问题归结为which单一责任组件类可以利用移动语义?一般的答案是:管理一个资源的任何东西。要点是移动构造函数/赋值器只是将资源重新安置到新对象并使旧对象无效,从而避免(假设是昂贵或不可能的)新分配和资源的深度复制。

So the question boils down to "which single-responsibility component class can take advantage of move semantics?" The general answer is: Anything that manages a resource. The point is that the move constructor/assigner will just reseat the resource to the new object and invalidate the old one, thus avoiding the (presumed expensive or impossible) new allocation and deep copying of the resource.

主要的例子是管理动态内存的任何东西,其中move操作只是复制指针并将旧对象的指针设置为零(因此旧对象的析构函数不做任何操作)。这是一个天真的例子:

The prime example is anything that manages dynamic memory, where the move operation simply copies the pointer and sets the old object's pointer to zero (so the old object's destructor does nothing). Here's a naive example:

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

关键是任何复制/移动构造函数都会完全复制成员变量;只有当这些变量本身是资源的句柄或指针时,您才能避免复制资源,因为移动的对象不再被认为有效,并且您可以自由地从中偷取资源。如果没有什么可偷,那么移动没有好处。

The key is that any copy/move constructor will do a full copying of the member variables; it is only when those variables are themselves handles or pointers to resources that you can avoid copying the resource, because of the agreement that a moved object is no longer considered valid and that you're free to steal from it. If there's nothing to steal, then there's no benefit in moving.

这篇关于移动构造函数和静态数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆