cpp结构体拷贝时发生的vector iterators incompatible等崩溃情况

⌚Time: 2024-02-03 07:21:26

👨‍💻Author: Jack Ge

结构体拷贝时的容器异常崩溃

自定义一个结构体


struct MMM{

    int a;

    std::vector<int> b;

}

在拷贝时发生异常

代码是


MMM m = mi;

或者


void func(MMM m){

    ...

}

...

func(mi);

都会造成崩溃

这个错误是因为在复制结构体的时候,其中的std::vector成员变量无法直接复制。等号复制和函数传参会调用默认的复制构造函数,都会造成崩溃

std::vector是一个动态数组,它使用了动态内存分配来存储元素。当你尝试直接复制一个std::vector对象时,复制的是指向动态内存的指针,而不是实际的数据。因此,当你尝试使用一个std::vector的复制构造函数或赋值运算符来复制结构体时,程序会抛出iterator incompatible错误。

要解决这个问题,需要自己实现结构体的复制构造函数和赋值运算符重载函数,来逐个复制其中的成员变量。以下是一个解决办法:


    // 自定义复制构造函数

    MMM(const MMM& other) {

        a = other.a;

        b = other.b;

    }

    

    // 自定义赋值运算符重载函数

    MMM& operator=(const MMM& other) {

        if (this != &other) {

            a = other.a;

            b = other.b;

        }

        return *this;

    }

这样之后再进行等号赋值或者作为函数参数传递就会调用自定义的拷贝构造函数,不会发生崩溃了

结构体拷贝崩溃的另一种情况

假设一个结构体具有自定义的拷贝构造函数,并且涉及到了内存中的字符操作


struct MM{

    MMM(const MMM& other) {

        ...

        strcpy_s(name,1024,other.name);

    }

    char *name;

};

而另一个结构体包含了关于这个结构体的数组


struct VV{

    int validNumber;//记录有效元素个数

    MMM ms[10];

};

如果使用赋值或者拷贝操作也会导致崩溃


VV v0;

...

VV v1 = v0;//崩溃

func(v0);//崩溃

原因是默认的对结构体拷贝,会对其中的数组每一个元素都进行拷贝操作,而有的元素并没有得到初始化,因此调用他的拷贝构造函数去操作结构体里的元素就会导致意想不到的情况和崩溃

解决办法还是在这个结构体自定义拷贝构造函数和赋值运算符,手动拷贝其中的数组元素,这样就可以避免意外崩溃


    // 自定义复制构造函数

    VV(const VV& other) {

        validNumber = other.validNumber;

        for(int i=0;i<validNumber;i++){

            ms[i] = other.ms[i];

        }

    }

    

    // 自定义赋值运算符重载函数

    VV& operator=(const VV& other) {

        if (this != &other) {

            validNumber = other.validNumber;

            for(int i=0;i<validNumber;i++){

                ms[i] = other.ms[i];

            }

        }

        return *this;

    }