【发布时间】:2016-02-01 09:33:20
【问题描述】:
在我的数值物理代码中,我需要使用unique_ptr 创建一个派生对象数组,它们的类型是基类。通常,我会:
// Header file of the Base class
class Particle{
public:
Particle(); // some constructor
virtual ~Particle(); // virtual destructor because of polymorphism
virtual function(); // some random function for demonstration
};
// Header file of the Derived class
class Electron : public Particle{
public:
Electron();
// additional things, dynamic_cast<>s, whatever
};
稍后在我的代码中,要使用 Base 类型指针创建一个 Derived 对象数组,我会这样做
Particle* electrons = new Electron[count];
优点是我能够以非常方便的方式使用数组electrons[number].function(),因为[] 中的增量值实际上是指向对象@987654327 的正确实例的内存地址@ 在数组中。但是,使用原始指针会很麻烦,所以我决定使用智能指针。
问题在于派生对象的定义。我可以做到以下几点:
std::unique_ptr<Particle, std::default_delete<Particle[]>> electrons(new Electron[count]);
它创建了多态电子数组,甚至使用了delete[] 的正确调用。问题在于调用数组的具体对象的方式,因为我必须这样做:
electrons.get()[number].function();
我不喜欢get() 部分,一点也不喜欢。
我可以做到以下几点:
std::unique_ptr<Particle[]> particles(new Particle[count]);
是的,在数组中调用Particle类型的实例
particles[number].function();
一切都会好起来的,除了我没有使用Electron类的具体细节的部分,因此代码没用。
现在有趣的部分,让我们再做一件事,好吗?
std::unique_ptr<Particle[]> electrons(new Electron[count]);
轰隆隆!
use of deleted function ‘std::unique_ptr<_Tp [], _Dp>::unique_ptr(_Up*) [with _Up = Electron; <template-
parameter-2-2> = void; _Tp = Particle; _Dp = std::default_delete<Particle []>]’
发生了什么事?
【问题讨论】:
-
该错误只是设计问题的症状。您的设计应该最好地区分数组的创建(请记住,数组本身不是多态的)和数组的多态使用。
-
用这条评论做你想做的事,因为它可能完全偏离轨道和/或实施的工作量太大,但是......我个人在(物理)模拟/数值实验方面的经验是一切都是已知的编译时间。我觉得有点奇怪,因此您使用的虚函数会严重减慢程序的速度。到目前为止,我已经设法完全避免了这些运行时的事情。
-
编译时 BOOMS 是您最好的朋友。 :-) 这是
unique_ptr的一个特性,它将运行时错误转化为编译时错误。 -
@JorenHeit 是的,事情在编译时是已知的,这是正确的,但是我也在努力使编码变得干净。例如,在这个直接的例子中,我正在使用离子和电子,许多东西可以很方便地变形,所以我不会重新复制和粘贴所有东西。如果这就是你的意思。
-
"优点是我能够以非常方便的方式使用数组
electrons[number].function()"...that's UB。
标签: c++ arrays c++11 polymorphism unique-ptr