繁体   English   中英

5复制和移动(构造函数和赋值)的C ++规则警告:复制或移动

[英]C++ Rule of 5 copy and move (constructor and assignment) caveat: to copy or move

我正在编写一个符合c ++ 11 +标准的类,现在是我实施5规则的时候了。

  1. 析构函数
  2. 复制构造函数
  3. 移动构造函数
  4. 复制分配运算符
  5. 移动分配运算符

我对复制/移动构造函数/分配有疑问。 据我了解,复制构造函数/赋值应该制作您类的副本(浅,深?)。 如果您的班级有唯一的成员,例如unique_ptr,我预见有两种情况。

  • 制作对象的深层副本

    就我而言,我不确定如何制作深层副本(请参见下面的代码)。

  • 将对象移到另一个类

    我认为,在复制构造函数中移动指针会对用户产生意想不到的副作用,因为他们期望复制,而不是移动,并且复制的原始对象将不再起作用。

    制作副本也可能会出现问题,但是就我而言,curl对象可能包含敏感信息,例如cookie或密码?


在具有这些约束的类中创建副本并移动构造函数/赋值的实际方法是什么? 要进行深层复制,移动还是不显式和隐式定义复制构造函数( delete关键字是否这样做 )?


// client.h
#pragma once

#include <Poco/URI.h>
#include <curl/curl.h>

class client
{
public:
    typedef Poco::URI uri_type;
    // Constructor
    client(const uri_type & auth);
    // Destructor
    virtual ~client();
    // Copy constructor
    client(const client & other);
    // Move constructor
    client(client && other);
    // Copy assignment
    client & operator=(const client & other);
    // Move assignment operator
    client & operator=(client && other);

private:
    uri_type auth_;
    // ... other variables (both unique and copyable) ommitted for simplicity.
    std::unique_ptr<CURL, void(*)(CURL*)> ptr_curl_;
};

// client.cpp
#include <memory>
#include <Poco/URI.h>
#include <curl/curl.h>

#include "client.h"

// Constructor
client::client(const uri_type & auth)
: auth_(auth)
, ptr_curl_(curl_easy_init(), curl_easy_cleanup)
{
    curl_global_init(CURL_GLOBAL_DEFAULT);
}

// Destructor
client::~client()
{
    curl_global_cleanup();
}

// Copy constructor
client::client(const client & other)
{
    // ... deep copy? move?
    // how would you deep copy a unique_ptr<CURL>?
}

// Move constructor
client::client(client && other)
{
    std::swap(*this, other);
}

// Copy assignment
client & client::operator=(const client & other)
{
    // Cant get this to work by making the copy happen in the parameter.
    client temp(other);
    std::swap(*this, temp);
    return *this;
}

// Move assignment operator
client & client::operator=(client && other)
{
    return *this;
}

顾名思义,复制构造函数/赋值运算符应始终COPY而不移动其成员,复制通常表示深复制。

请记住:默认情况下,c ++中的所有对象都应具有值语义,即,它们的行为应类似于int

此外,帖子中的术语表明您正在将唯一对象(单子)与unique_ptr指向的对象混淆。 大多数不可复制的对象是处理程序(例如unique_ptr处理堆上的对象),在这种情况下,您将复制它们处理的内容。 如果这不可能,那么很可能根本就没有实现对象的副本构造函数的意义。

如果您的对象拥有对唯一资源的拥有引用(项目中只能有一个实例),那么第一个问题是:可以共享吗? ->使用shared_ptr。 如果不是->不要复制。 如果您的对象拥有对唯一资源(原始指针或引用)的非所有者引用,请复制该引用。 在这两种情况下,请注意,您现在都有两个对象,它们共享部分状态,即使在非多线程应用程序中,这也可能很危险。

对于某些类型,使用复制构造函数是不合适的。 这包括大多数在语义上包含不可复制类型的类型。 (不计算unique_ptr ,不计算CURL实例)

如果libcurl具有“ duplicate_handle”功能,则您的副本构造函数应使用它来初始化副本中的unique_ptr。 否则,您应该删除副本构造函数,而仅实现move。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM