std::vector 个 Derived class 个实例,其 Bases 包含(原始)指针
std::vector of Derived class instances whose Bases contain a (raw) pointer
假设我有以下结构
class BaseKernel {
// .......
}
class DerivedKernel : public BaseKernel {
// .......
}
class A {
public:
A(BaseKernel* kernel) : kernel(kernel) {}
A(const A& a) : kernel(a.kernel) {}
~A() {delete kernel;}
BaseKernel* kernel;
}
class B : public A {
public:
B(BaseKernel* kernel) : A(kernel) {}
B(const B& b) : A(b) {}
~B() = default;
}
class C : public B {
public:
C() = default;
C(BaseKernel* kernel) : B(kernel) {}
C(const C& c) : B(c) {}
~C() = default;
}
class D {
public:
D() = default;
D(std::vector<C> collection) : collection(collection) {}
std::vector<C> collection;
}
class E {
public:
E(std::vector<D> dollection) : dollection(dollection) {} // lmfao, dollection for the lack of a better word
std::vector<D> dollection;
}
有以下用法
BaseKernel* kernel1 = new DerivedKernel(...);
BaseKernel* kernel2 = new DerivedKernel(...);
C c_obj1(kernel1);
C c_obj2(kernel2);
std::vector<C> collection1(1, c_obj1);
std::vector<C> collection2(1, c_obj2);
std::vector<D> dollections = {collection1, collection2};
// At this point kernel1 and kernel2 are deleted.
E e_obj(dollections) // Useless now
由于我是 C++ 的新手,因此不熟悉智能指针(但我相信解决方案是使用后者),我将如何使用原始指针处理这种情况? (更好的是,使用适当的智能指针的解决方案会很棒)
c_obj1
和 c_obj2
的初始化很好(kernel1
和 kernel2
仍然存在),但特别是 dollections
我需要初始化带括号的向量(因为我会有不同的 collections
),调试后它首先通过复制构造函数,然后最终通过析构函数 ~A()
?
我发现了一些问题。我会看看我是否能理解你真正的问题。让我们从这个开始:
class A {
public:
A(BaseKernel* kernel) : kernel(kernel) {}
A(const A& a) : kernel(a.kernel) {}
~A() {delete kernel;}
BaseKernel* kernel;
}
这很糟糕。如果您使用复制构造函数,您将最终删除相同的数据两次。想象一下:
BaseKernel * k = new BaseKernel();
A first(k);
A second(first);
这个this点,first.kernel和second.kernel都指向k。现在,当它们超出范围时,两个析构函数都会尝试删除它们的内核指针,因此 k 将被删除两次。
我不太明白你问的问题。但是,我不鼓励使用原始指针并鼓励使用智能指针。 std::unique_ptr
效率更高,但我倾向于总是使用 std::shared_ptr
如下:
class A {
public:
A(std:: shared_ptr <BaseKernel> kernelIn) : kernel(kernelIn) {}
A(const A& a) : kernel(a.kernel) {}
~A() { /* Nothing needed */ }
std:: shared_ptr <BaseKernel> kernel;
};
然后……
std::shared_ptr<BaseKernel> kernel1 = std::make_shared<DerivedKernel>(...);
不过,您可能需要做一个 dynamic_pointer_cast
。我通常不喜欢使用我指向的数据类型,所以通常不会在这里使用,而是:
std::shared_ptr< DerivedKernel> kernel1 = std::make_shared<DerivedKernel>(...);
然后 dynamic_pointer_cast 稍后根据需要进行。
我不确定这是否能让你更进一步。
假设我有以下结构
class BaseKernel {
// .......
}
class DerivedKernel : public BaseKernel {
// .......
}
class A {
public:
A(BaseKernel* kernel) : kernel(kernel) {}
A(const A& a) : kernel(a.kernel) {}
~A() {delete kernel;}
BaseKernel* kernel;
}
class B : public A {
public:
B(BaseKernel* kernel) : A(kernel) {}
B(const B& b) : A(b) {}
~B() = default;
}
class C : public B {
public:
C() = default;
C(BaseKernel* kernel) : B(kernel) {}
C(const C& c) : B(c) {}
~C() = default;
}
class D {
public:
D() = default;
D(std::vector<C> collection) : collection(collection) {}
std::vector<C> collection;
}
class E {
public:
E(std::vector<D> dollection) : dollection(dollection) {} // lmfao, dollection for the lack of a better word
std::vector<D> dollection;
}
有以下用法
BaseKernel* kernel1 = new DerivedKernel(...);
BaseKernel* kernel2 = new DerivedKernel(...);
C c_obj1(kernel1);
C c_obj2(kernel2);
std::vector<C> collection1(1, c_obj1);
std::vector<C> collection2(1, c_obj2);
std::vector<D> dollections = {collection1, collection2};
// At this point kernel1 and kernel2 are deleted.
E e_obj(dollections) // Useless now
由于我是 C++ 的新手,因此不熟悉智能指针(但我相信解决方案是使用后者),我将如何使用原始指针处理这种情况? (更好的是,使用适当的智能指针的解决方案会很棒)
c_obj1
和 c_obj2
的初始化很好(kernel1
和 kernel2
仍然存在),但特别是 dollections
我需要初始化带括号的向量(因为我会有不同的 collections
),调试后它首先通过复制构造函数,然后最终通过析构函数 ~A()
?
我发现了一些问题。我会看看我是否能理解你真正的问题。让我们从这个开始:
class A {
public:
A(BaseKernel* kernel) : kernel(kernel) {}
A(const A& a) : kernel(a.kernel) {}
~A() {delete kernel;}
BaseKernel* kernel;
}
这很糟糕。如果您使用复制构造函数,您将最终删除相同的数据两次。想象一下:
BaseKernel * k = new BaseKernel();
A first(k);
A second(first);
这个this点,first.kernel和second.kernel都指向k。现在,当它们超出范围时,两个析构函数都会尝试删除它们的内核指针,因此 k 将被删除两次。
我不太明白你问的问题。但是,我不鼓励使用原始指针并鼓励使用智能指针。 std::unique_ptr
效率更高,但我倾向于总是使用 std::shared_ptr
如下:
class A {
public:
A(std:: shared_ptr <BaseKernel> kernelIn) : kernel(kernelIn) {}
A(const A& a) : kernel(a.kernel) {}
~A() { /* Nothing needed */ }
std:: shared_ptr <BaseKernel> kernel;
};
然后……
std::shared_ptr<BaseKernel> kernel1 = std::make_shared<DerivedKernel>(...);
不过,您可能需要做一个 dynamic_pointer_cast
。我通常不喜欢使用我指向的数据类型,所以通常不会在这里使用,而是:
std::shared_ptr< DerivedKernel> kernel1 = std::make_shared<DerivedKernel>(...);
然后 dynamic_pointer_cast 稍后根据需要进行。
我不确定这是否能让你更进一步。