class 个对象的 C++ 向量和动态内存分配 - 第 2 部分

C++ vector of class objects and dynamic memory allocation - part 2

这是对我之前在此处发布的问题 () 的跟进。

为了这个例子,

Someclass 是一个过于简化的 class。重要的是要知道这个 class 的对象存储在其他地方的向量中。

Buffer 是另一个 class,它具有三种类型的成员:常规变量 (NAME)、向量 (S) 和指向动态分配的内存块 (DATA) 的指针。

如果我注释 v.erase(v.begin()+1); 行,那么代码会编译并运行良好。 Bur erase 产生许多错误,例如“使用已删除的函数 Buffer& Buffer::operator=(const Buffer&)”。

我想我了解问题,但不知道如何解决。你能修改我的例子让它工作吗?请注意,该示例过于简单,我需要保留这两个 classes 和向量的使用。

谢谢。

using namespace std;

#include <cstdlib>
#include <vector>
#include <string>

using namespace std;

class Someclass
{
public:
    int I;
    Someclass(int i) {I = i;};

private:
};

class Buffer
{
public:
    vector <Someclass> S;
    string NAME;
    float *DATA;

    Buffer(int length, string name) {DATA = (float*) calloc (length,sizeof(float)); NAME = name;};
    Buffer(const Buffer &buffer) = delete;
    Buffer(Buffer&& buffer) { 
        S = buffer.S;
        NAME = buffer.NAME;
        DATA = buffer.DATA;
        buffer.DATA = nullptr;
    }
    ~Buffer(){
        S.clear();
        if (DATA) free(DATA);
    };
    
private:
};

int main(int argc, char** argv)
{
    vector <Buffer> v;
    for (int i =0; i<10; i++)
    {
        cout<<i<<endl;
        v.push_back(Buffer(1000,"name"));

    }
    v.erase(v.begin()+1);
    v.clear();
    return 0;
}

这是因为一个简单的原因。当您擦除一个条目时,阵列需要移除该“气泡”(即空槽)并压缩阵列。这意味着它需要移动一些东西。所以在搬家的时候,他们的做法是这样的,

// Form the MSVC xutility.h file.
for (; _First != _Last; ++_Dest, (void) ++_First) {
        *_Dest = _STD move(*_First);
    }

如您所见,他们移动它的方式是移动各个条目。这意味着您调用对象 Buffer 的复制赋值/移动赋值运算符。但是您没有定义任何赋值运算符,而是定义了一个移动构造函数。这告诉编译器,

“嘿,这个 Buffer 对象只有一个移动构造函数。也许用户只是想通过移动另一个构造 class。所以它不能有任何其他赋值(复制和移动)”

所以现在编译器不会为您生成它们。这意味着您现在不能将另一个 Buffer 复制或移动到另一个(除非您移动构建它)。这就是错误的原因。

解决方案是添加一个移动赋值运算符。

Buffer& operator=(Buffer&& other)
{
    S = std::move(other.S);
    NAME = std::move(other.NAME);
    DATA = other.DATA;

    other.DATA = nullptr;   // Make sure to set it to nullptr.

    return *this;
}