如何为这种C++结构实现复制操作符?

Rel*_*lla 1 c++ oop copy class operators

所以有

struct ResultStructure
{
    ResultStructure(const ResultStructure& other)
    {
        // copy code in here ? using memcpy ? how???  
    }
    ResultStructure& operator=(const ResultStructure& other)
    {
        if (this != &other) {
            // copy code in here ?
        }
        return *this
    }
    int length;
    char* ptr;
};
Run Code Online (Sandbox Code Playgroud)

如何实现"复制构造函数"和"赋值运算符"?(抱歉 - 我是C++ nube)

更新:sbi和其他人问 - 为什么我要手动处理原始内存?我的答案很简单 - 在学生项目中,我现在使用了很多C库,例如OpenCV OpenAL和FFmpeg,还有更多.目前使用C++我们尝试创建一个基于图形的直接显示,如跨平台库,这将有助于实时视频广播和处理.我们的图元素目前使用char*和int对进行数据交换.要将数据转换为订阅元素,我们现在使用原始memcpy.我想更进一步,让我们可以使我们的图元素基于C++模板.因此,一个图元素将能够与其他Graph元素共享当前图元素数据,并且它共享的数据将是一个结构,其中不包含一个char*one int,而是包含任意数量的数据字段和几乎任何内部元素.这就是为什么我需要了解如何创建一个实现"复制构造函数"和"赋值运算符"的基本C++结构,以便我能够使用新的数据转换算法,如

void CastData(T item){
    for(size_t i = 0 ; i < FuncVec.size(); i++){
        T dataCopy = item;
        FuncVec[i](dataCopy);
    }
}
Run Code Online (Sandbox Code Playgroud)

而不是目前使用

void CastData(char * data, int length){
    for(size_t i = 0 ; i < FuncVec.size(); i++){
        char* dataCopy = new char[length];
        memcpy(dataCopy, data, length);
        FuncVec[i](dataCopy, length);
                    delete[] dataCopy;
    }
}
Run Code Online (Sandbox Code Playgroud)

Naw*_*waz 9

如果您使用std::string,而不是char*,您甚至不需要编写operator=或复制构造函数.编译器生成的代码可以很好地完成您的工作.

但作为一般解决方案(对于其他一些场景),请使用复制和交换习惯用法:

例外C++通过香草萨特 非常详细描述了这些.我建议你阅读这本书中的内容.目前,您可以在线阅读本文:


sbi*_*sbi 9

您可能想要解释为什么要手动处理原始内存.我很久没有这样做了,它是为什么std::string以及std::vector在哪里设计的:

struct ResultStructure
{
    // nothing else needed

    std::string data; // or std::vector<char>
};
Run Code Online (Sandbox Code Playgroud)

但是,如果你真的需要这么做(这是家庭作业吗?),那么首先要知道这是非常难以做到这一点.例如,赋值运算符的简单实现可能如下所示:

// DON'T TRY THIS AT HOME!!
ResultStructure& ResultStructure::operator=(const ResultStructure& rhs)
{
  delete[] ptr;                               // free old ressource
  ptr = new char[rhs.length];                 // allocate new resourse
  std::copy(rhs.ptr, rhs.ptr+rhs.length, ptr; // copy data
  length = rhs.length;
}
Run Code Online (Sandbox Code Playgroud)

如果有人意外地将一个对象分配给自己(如果你拥有的是两个引用并且你不怀疑它们引用同一个对象,则可能会发生这种情况),那么这将导致致命的失败.
另外,如果new抛出异常怎么办?(std::bad_alloc如果内存耗尽,它可能会抛出.)然后我们已经删除了旧数据并且没有分配新数据.然而,指针仍指向旧数据的位置(实际上,我认为这是实现定义的,但我还没有看到删除后更改ptr的实现),以及类的析构函数(你知道)那个类需要一个析构函数,对吗?)然后会尝试在没有分配数据的地址删除一段数据.这是未定义的行为.你可以期待的最好的是它会立即崩溃.

最简单的方法是使用Copy-And-Swap习语:

struct ResultStructure
{
    ResultStructure(const ResultStructure& other)
     : ptr(new char[rhs.length]), length(rhs.length)
    {
        std::copy(rhs.ptr, rhs.ptr+rhs.length, ptr);
    }

    ~ResultStructure() // your class needs this
    {
      delete[] ptr;
    }

    ResultStructure& operator=(ResultStructure rhs) // note: passed by copy
    {
        this->swap(rhs);
        return *this
    }

    void swap(const ResultStruct& rhs)
    {
      using std::swap;
      swap(length, rhs.length); 
      swap(ptr, rhs.ptr); 
    }

    std::size_t length;
    char* ptr;
};
Run Code Online (Sandbox Code Playgroud)

请注意,我添加了一个析构函数,更改了赋值运算符以传递每个副本的参数(我们需要调用复制构造函数来分配内存),并添加了一个swap成员函数.按照惯例,swap()函数永远不会抛出并且很快,最好是O(1).

我知道GMan对Copy-And-Swap成语的讨论已经足够详尽,而且虽然对来说可能太简洁了,但你最初可能不会理解很多,但是要坚持并理解为尽可能多.