我在 C++ 中有一个 objcet,我通过extern "c"
它作为指针导出。为了能够创建对象并返回它,我必须在堆上进行,考虑到尝试返回本地范围变量的范围问题。但是,为了在堆上分配,我必须能够复制一个我正在努力做的对象。这是一个例子:
#include <iostream>
using namespace std;
// used to simulate complex data structure in nex object
class DataStorage {
private:
int a;
public:
explicit DataStorage(int a) : a(a) {
}
};
// object for export "C". Contains some pointers.
class NonTrivialObject {
public:
int *int_ptr;
char *char_ptr;
double *double_ptr;
DataStorage *data_storage_ptr;
NonTrivialObject(int *int_ptr, char *char_ptr, double *double_ptr, DataStorage *data_storage_ptr)
: int_ptr(int_ptr), char_ptr(char_ptr), double_ptr(double_ptr), data_storage_ptr(data_storage_ptr) {}
~NonTrivialObject() {
/*
* only delete objects of allocated on heap
*/
}
/*
* Copy constructor
*/
NonTrivialObject(const NonTrivialObject &rhs) {
if (this != &rhs) {
this->int_ptr = rhs.int_ptr;
this->char_ptr = rhs.char_ptr;
this->double_ptr = rhs.double_ptr;
this->data_storage_ptr = rhs.data_storage_ptr;
}
}
/*
* Copy assignment constructor
*/
NonTrivialObject &operator=(const NonTrivialObject &rhs) {
if (this != &rhs) {
this->int_ptr = rhs.int_ptr;
this->char_ptr = rhs.char_ptr;
this->double_ptr = rhs.double_ptr;
this->data_storage_ptr = rhs.data_storage_ptr;
}
return *this;
}
/*
* Move assignment constructor
*/
NonTrivialObject &operator=(NonTrivialObject &&rhs) noexcept {
if (this != &rhs) {
this->int_ptr = rhs.int_ptr;
this->char_ptr = rhs.char_ptr;
this->double_ptr = rhs.double_ptr;
this->data_storage_ptr = rhs.data_storage_ptr;
}
return *this;
}
/*
* Move constructor
*/
NonTrivialObject(NonTrivialObject &&rhs) noexcept {
if (this != &rhs) {
this->int_ptr = rhs.int_ptr;
this->char_ptr = rhs.char_ptr;
this->double_ptr = rhs.double_ptr;
this->data_storage_ptr = rhs.data_storage_ptr;
}
}
};
extern "C" {
// first method will not work because nonTrivialObjectPtr is locally scoped
NonTrivialObject *CopyANonTrivialObject1(NonTrivialObject obj) {
auto *nonTrivialObjectPtr = (NonTrivialObject *) malloc(sizeof(obj));
nonTrivialObjectPtr = &obj;
return nonTrivialObjectPtr;//Address of local variable may escape the function
}
// Only creates a local copy, presumably due to the contents of copy operator
NonTrivialObject *CopyANonTrivialObject2(NonTrivialObject obj) {
auto *nonTrivialObjectPtr = (NonTrivialObject *) malloc(sizeof(obj));
*nonTrivialObjectPtr = obj;
return nonTrivialObjectPtr;
}
}
int main() {
int i = 3;
char c = 's';
double dub = 3.98;
DataStorage dataStorage(4);
NonTrivialObject nonTrivialObject(&i, &c, &dub, &dataStorage);
NonTrivialObject* nonTrivialObject2 = CopyANonTrivialObject2(nonTrivialObject);
cout << nonTrivialObject.int_ptr << ", " << *nonTrivialObject.int_ptr << endl;
cout << nonTrivialObject2->int_ptr << ", " << *nonTrivialObject2->int_ptr << endl;
free(nonTrivialObject2);
return 0;
};
将输出
0x7ffd59c4ac28, 3
0x7ffd59c4ac28, 3
表明该副本是浅拷贝。我知道
/*
* Copy constructor
*/
NonTrivialObject(const NonTrivialObject &rhs) {
if (this != &rhs) {
this->int_ptr = rhs.int_ptr;
this->char_ptr = rhs.char_ptr;
this->double_ptr = rhs.double_ptr;
this->data_storage_ptr = rhs.data_storage_ptr;
}
}
是问题,但为了修复它,我不断遇到分段错误。我尝试了各种形式的取消引用和获取内存地址以及尝试用memcpy
and替换分配std::copy
,这两种方法在 valgrind 中都非常不受欢迎。
我如何将此类修改为完全可复制,以便保存数据的内存位置不同但值相同?