实现非复制交换功能

时间:2017-04-26 13:11:22

标签: c++ move

我想创建像:

这样的函数
void func(sample &a){
    sample b();
    std::swap(b,a);
}

问题是,当我使用swap时总是使用复制构造函数,并且析构函数应用于交换函数中使用的临时对象。

是否有可能实现非复制交换?

2 个答案:

答案 0 :(得分:2)

解决问题的C ++ 11解决方案是在sample类中提供移动构造函数和移动赋值运算符。然后,std::swap将使用移动而不是复制操作,这应该更有效(你仍然会看到析构函数被调用,但这通常是在一个“空”对象上,应该非常便宜)。 / p>

通常,如果您正在编写自己的复制构造函数和复制赋值运算符,那么您还需要编写移动构造函数并移动赋值运算符(当然还有析构函数) - 这就是“5的规则”在C ++ 11中,它扩展了C ++ 98中已知的“3规则”。例如,考虑手动管理内存的这个(坏)示例类(N.B.这只是展示的一个例子,在现实生活中使用std::vectorstd::unique_ptr而不是这样做):

class example {
public:
    example() 
        : ptr{new int[1024]}
    {}

    example(const example& other)
        : ptr{new int[1024]}
    {
        // Copy other's member array
        std::copy(other.ptr, other.ptr + 1024, ptr);
    }

    example& operator=(const example& other)
    {
         if (this != &other) {
             std::copy(other.ptr, other.ptr + 1024, ptr);
         }
         return *this;
    }

    ~example()
    {
        delete[](ptr); 
    }

    example(example&& other)
        : ptr(other.ptr) // "steal" other's ptr
    {
        other.ptr = nullptr;
    }

    example& operator=(example&& other)
    {
        std::swap(ptr, other.ptr);
        return *this;
    }

private:
    int* ptr;
};

现在,当你std::swap两个example时,交换函数将使用移动操作,不会发生额外的分配,只有一些(便宜的)指针交换,以及一个无操作调用delete[](nullptr)

答案 1 :(得分:-1)

您的函数将a与默认构造的对象交换。如果这是预期的语义,那就

a = sample();

并根据需要提供移动构造函数和赋值。