You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++类拷贝后成员指针指向异常问题求助

类拷贝后成员指针指向原实例数组的问题:原因与解决方法

问题原因

C++编译器会为未显式定义拷贝构造函数和拷贝赋值运算符的类生成默认浅拷贝实现。对于你的A类来说,默认拷贝只会直接复制成员变量的值:

  • 数组arr是值类型,会被完整复制到新实例的内存空间,新实例的arr地址和原实例不同;
  • 指针item1/item2/item3会被直接复制原地址,导致新实例的指针依然指向原实例的arr元素,而不是自身的arr数组。

这就是为什么你会看到b.a.item1和原实例a.item1地址相同,但b.a.arr[0]地址不同的原因。

解决方法

需要手动实现A类的拷贝构造函数和拷贝赋值运算符,在拷贝过程中重新将指针绑定到当前实例的arr数组元素上,确保拷贝后的指针指向自身数组。

修改后的完整代码:

#include <iostream>

class A {
public:
    long arr[3] = {0x10, 0x20, 0x30};
    long *item1 = &arr[0], *item2 = &arr[1], *item3 = &arr[2];

    // 保留默认构造函数
    A() = default;

    // 自定义拷贝构造函数
    A(const A& other) {
        // 复制原实例的数组内容
        for (int i = 0; i < 3; ++i) {
            arr[i] = other.arr[i];
        }
        // 将指针重新绑定到当前实例的arr元素
        item1 = &arr[0];
        item2 = &arr[1];
        item3 = &arr[2];
    }

    // 自定义拷贝赋值运算符
    A& operator=(const A& other) {
        // 防止自赋值导致的错误
        if (this != &other) {
            // 复制数组内容
            for (int i = 0; i < 3; ++i) {
                arr[i] = other.arr[i];
            }
            // 重新绑定指针
            item1 = &arr[0];
            item2 = &arr[1];
            item3 = &arr[2];
        }
        return *this;
    }
};

class B {
public:
    A a;

    // 构造函数可以保留值传递,现在拷贝会正确处理指针
    B(A param) : a(param) {}
};

int main() {
    A a = A();
    B b = B(a);

    std::cout << &a.arr[0] << std::endl;
    std::cout << a.item1 << std::endl;

    std::cout << &b.a.arr[0] << std::endl;
    std::cout << b.a.item1 << std::endl;
}

补充说明

  • 实现拷贝构造和赋值运算符时,要注意防止自赋值(即this != &other的判断),避免不必要的操作或潜在错误;
  • 如果不想维护指针,也可以考虑将item1等改为返回数组元素引用的成员函数,比如:
    long& item1() { return arr[0]; }
    const long& item1() const { return arr[0]; }
    
    这种方式不需要处理拷贝时的指针绑定问题,也能达到访问数组元素的目的。

内容的提问来源于stack exchange,提问作者BuhtanDingDing

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 03:08:11