改变堆上一个对象其中一个成员变量,导致另外一个成员变量隐含改变的问题?

问题背景

学习实现网络编程的无阻塞读写数据。
设计类Buffer作为读写数据的缓存,设计类Connection管理一个已经建立连接的Tcp连接,其中有两个Buffer分别负责读和写的数据缓存。类图如下:

img

每建立一个连接,我都用智能指针创建一个在堆上的Connection类,两个Buffer采用默认构造函数并将其成员变量vector<char> data_初始化为长度为1024的vector,两个idx初始化为0。
Buffer中有一个将读取数据添加到data_缓存的方法void addData(),该方法中有一条命令

void addData(const char* data, int len) {
    ...
    data_[write_idx_++] = *data++;
    ...
}

我需要将read()到的数据保存到ConnectionBuffer input_中,因此调用input_.addData()来实现这个目的。

但是在debug中,只要一执行上边这条命令

data_[write_idx_++] = *data++;

我的Connection中的另一个成员变量Buffer output_其中的int read_idx_就会改变,当超出其内存时,int write_idx_也开始发生改变,最后两个成员变量都从0变成很大的数。

原因与尝试

我猜测原因是,我的Conncetion对象放在堆上(智能指针),而我在向ConnectionBuffer input_vector<char> data_中写数据时(vector数据也存放在堆上),vector保存实际数据的地址正好是另一个成员变量output_的地址。但我又觉得不应该,vector保存实际数据的堆地址应该是干净的才对。
因此我尝试将两个Buffer变成指向堆上的指针,然后再在析构函数中delete,确实解决了问题。

问题

我不知道我的猜测原因对不对,而且我猜测的原因也很不清晰,因此还是难以理解这个问题,想象不出来我的Connection对象的两个Buffer成员变量,以及Buffer自己的成员变量(data_, read_idx_, write_idx_)在堆上的内存分布。
因此想请教对c++对象在堆上的内存分布理解更深入的朋友谈谈这个问题。
以及,如果我不采用Buffer*而非要使用Buffer作为成员变量时,该如何避免这个问题。
感激不尽!

关于问题原因的猜测:

您的猜测是错误的,因为即使数据指针在内存中的地址与另一个对象的成员变量指针的地址相同,它们也不会相互干扰。这是因为每个对象在内存中都有独立的地址空间,不同对象之间不会互相影响。

关于问题的解决方法:

由于您的 Connection 类的两个 Buffer 对象需要共享同一个连接的数据,因此可以通过引用计数的方式来解决这个问题,而无需使用指针。具体来说,可以将 Buffer 对象中的 vector data_ 成员变量改为 shared_ptr<vector> data_,这样就可以使用共享指针来管理实际数据的内存。在创建 Connection 对象时,可以将 input_ 和 output_ 的 data_ 成员变量初始化为相同的 shared_ptr<vector> 对象,这样它们就共享同一个数据缓存了。当某个 Connection 对象被销毁时,其对应的 data_ 引用计数会自动减一,当最后一个引用计数为0时,vector 对象就会被销毁。

另外,如果您仍然想使用原来的指针方案,也可以采用以下方法来避免问题:

在 Connection 类的析构函数中,显式地释放 input_ 和 output_ 对象的 data_ 指针:

~Connection() {
    delete input_.data_;
    delete output_.data_;
}

这样可以确保在 Connection 对象被销毁时,其对应的 data_ 指针所指向的内存也被正确地释放掉了。