如何复制 class 的实例,其中嵌套 class 包含指向外部 class 的指针成员?
How do I copy an instance of a class with a nested class containing a pointer member to the outer class?
这里是 C++ 程序员新手。假设我有一个 class Outer 和一个嵌套的 class Inner。 Inner 包含一个指针成员,在构造期间设置为 Outer。 Outer 包含一个 AddNewInner() 函数,它创建一个指向自身的新 Inner 并将其添加到一个向量中。
class Outer {
public:
class Inner {
public:
Inner(Outer* outerParent) : mOuterParent(outerParent) {}
Outer* mOuterParent;
}
void AddNewInner() {
Inner newInner(this);
mInnersVec.push_back(newInner);
}
vector<Inner> mInnersVec;
}
这在创建 Outer 的新实例并调用 AddNewInner() 以将 Inners 添加到向量时工作正常。但是,当我尝试创建 Outer 实例的副本时,我遇到了一个问题:Outer 副本的 Inners 向量不指向副本(本身),它们仍然指向原始 Outer。
Outer outerA;
outerA.AddNewInner();
Outer* ptrA = outerA.mInnersVec[0].mOuterParent; // this points to outerA, good!
Outer outerB = outerA;
Outer* ptrB = outerB.mInnersVec[0].mOuterParent; // this still points to outerA, bad!
我需要副本中 Inners 的向量指向副本,而不是原件。完成此任务的最佳方法是什么,或者是否有其他方法可以完成同样的事情?
您需要为您的 class 使用自定义 copy constructor/assignment operator。这将允许您对 Outer* mOuterParent
变量进行深度复制;可能会创建一个新的。
复制指针时,您复制的是指向内存中特定地址 space 的变量。复制指针只会让您能够通过两个 'accessor variables'.
访问相同的 'true variable'
在您的示例中,特定 outer
对象的 Outer* mOuterParent
变量将 始终 指向 outer
class 由该指针指向,无论您复制了多少个特定对象。
正确,这是预期的行为。在 C++ 中创建对象的副本时,编译器使用 复制构造函数 。如果您还没有为 class 编写自己的复制构造函数,那么它会使用编译器生成的复制构造函数,它只是依次为每个成员运行(可能生成的)复制构造函数。
所以当复制一个 Outer
时,事件的顺序是这样的:
- 编译器为
Outer
运行(生成的)复制构造函数
- 这会运行
std::vector
的复制构造函数。这个构造函数为新的vector分配存储空间,然后依次为每个元素运行复制构造函数
- 因此
Inner
的(生成的)复制构造函数针对每个元素运行,它只复制成员指针(仍然指向原始 Outer
)。
为了在复制 Outer
时更新 Inner
元素,您需要为 Outer
编写一个自定义复制构造函数,它可以根据需要更新指针。像这样:
Outer::Outer(const Outer& other)
: mInnersVec(other.mInnersVec) // Do initial vector copy
{
// Update vector elements
for (auto& elem : mInnersVec) {
elem.mOuterParent = this;
}
}
请注意,每当您编写自定义复制构造函数时,您几乎总是也需要编写自定义赋值运算符。我建议您阅读您最喜欢的 C++ 教科书中的复制和赋值 :-)。
这里是 C++ 程序员新手。假设我有一个 class Outer 和一个嵌套的 class Inner。 Inner 包含一个指针成员,在构造期间设置为 Outer。 Outer 包含一个 AddNewInner() 函数,它创建一个指向自身的新 Inner 并将其添加到一个向量中。
class Outer {
public:
class Inner {
public:
Inner(Outer* outerParent) : mOuterParent(outerParent) {}
Outer* mOuterParent;
}
void AddNewInner() {
Inner newInner(this);
mInnersVec.push_back(newInner);
}
vector<Inner> mInnersVec;
}
这在创建 Outer 的新实例并调用 AddNewInner() 以将 Inners 添加到向量时工作正常。但是,当我尝试创建 Outer 实例的副本时,我遇到了一个问题:Outer 副本的 Inners 向量不指向副本(本身),它们仍然指向原始 Outer。
Outer outerA;
outerA.AddNewInner();
Outer* ptrA = outerA.mInnersVec[0].mOuterParent; // this points to outerA, good!
Outer outerB = outerA;
Outer* ptrB = outerB.mInnersVec[0].mOuterParent; // this still points to outerA, bad!
我需要副本中 Inners 的向量指向副本,而不是原件。完成此任务的最佳方法是什么,或者是否有其他方法可以完成同样的事情?
您需要为您的 class 使用自定义 copy constructor/assignment operator。这将允许您对 Outer* mOuterParent
变量进行深度复制;可能会创建一个新的。
复制指针时,您复制的是指向内存中特定地址 space 的变量。复制指针只会让您能够通过两个 'accessor variables'.
访问相同的 'true variable'在您的示例中,特定 outer
对象的 Outer* mOuterParent
变量将 始终 指向 outer
class 由该指针指向,无论您复制了多少个特定对象。
正确,这是预期的行为。在 C++ 中创建对象的副本时,编译器使用 复制构造函数 。如果您还没有为 class 编写自己的复制构造函数,那么它会使用编译器生成的复制构造函数,它只是依次为每个成员运行(可能生成的)复制构造函数。
所以当复制一个 Outer
时,事件的顺序是这样的:
- 编译器为
Outer
运行(生成的)复制构造函数
- 这会运行
std::vector
的复制构造函数。这个构造函数为新的vector分配存储空间,然后依次为每个元素运行复制构造函数 - 因此
Inner
的(生成的)复制构造函数针对每个元素运行,它只复制成员指针(仍然指向原始Outer
)。
为了在复制 Outer
时更新 Inner
元素,您需要为 Outer
编写一个自定义复制构造函数,它可以根据需要更新指针。像这样:
Outer::Outer(const Outer& other)
: mInnersVec(other.mInnersVec) // Do initial vector copy
{
// Update vector elements
for (auto& elem : mInnersVec) {
elem.mOuterParent = this;
}
}
请注意,每当您编写自定义复制构造函数时,您几乎总是也需要编写自定义赋值运算符。我建议您阅读您最喜欢的 C++ 教科书中的复制和赋值 :-)。