问题描述
我需要什么
我需要一个容器来存储对象 A
和派生子类 B
的实例。具体来说,我需要实现以下任务:
示例
头文件可能如下所示:
int globalB = 5;
// Base class
class A {
public:
A(a) : a(a);
~A();
int a;
virtual int get_b() {
return globalB;
}
};
// Derived class
class B : public A {
public:
B(a,b) : A(a),b(b);
~B();
int a;
int b;
int get_b() {
return b;
}
};
// Container
class Container {
public:
Container();
~Container();
// adds an A element
void add_element(a);
// adds a B element
void add_element(a,b);
// removes all elements with (elem.a == 0)
void remove_a0_elements();
// Iterator (I will still have to figure out how this is done properly)
struct Iterator { /* ... */ };
};
static int example_usage() {
auto container = Container();
for (int a=1; i<=100; i++) {
container.add_element(a);
container.add_element(a,a);
}
int sum = 0;
for (auto &elem : container) {
sum += elem.get_b();
}
return sum;
}
请注意,与示例所建议的不同,元素不会在连续操作中添加,而是在程序中随机添加。当然,我用来完成示例中的任务的容器的任何结构也都很好(例如,通过移交而不是就地构建来添加元素)。如果有一些内存开销,那不会是主要问题,因为所有对象加在一起并不是很大。
我目前的想法
我想过使用 std::unique_ptr
的向量来完成任务,如建议的 here。但是,我担心内存会以这种方式分散,从而大大降低迭代的性能(参见 here)。另一个想法是让 Container
包装两个向量 - 分别是 A
和 B
- 但是我不知道如何构建迭代器。此外,这将使使用更多子类变得困难(我需要它至少适用于两对基类和子类)。
问题
- 是否有任何标准容器可以满足我的需求?
- 如果没有,根据需要实现容器的优雅方式是什么?
- 有没有办法“保留”一块内存来构造
Container
的元素而不知道它们的大小?然后我可以包装一个指针向量并规避内存分散的问题。
解决方法
容器类型和元素存储的选择在这里实际上正交:即使元素单独分配,def histogram_boxplot(feature,figsize=(15,10),bins=None):
f,(ax_box,ax_hist)=plt.subplots(nrows=2,sharex=True,gridspec_kw={'height_ratios':(.25,.75)},figsize=figsize)
sns.distplot(feature,kde=False,ax=ax_hist,bins=bins)
sns.boxplot(feature,ax=ax_box,color='Red')
ax_hist.axvline(np.mean(feature),color='g',linestyle='-')
ax_hist.axvline(np.median(feature),color='y',linestyle='--')
也不能同时支持高效的删除和迭代 /em>。您当然可以std::vector<std::unique_ptr<A>>
一个元素,但是您必须花时间跳过每次迭代。
可以使用空闲列表来扩充数据结构以允许重用空槽,并使用空槽计数来允许在迭代期间有效地跳过它们。结果是 “colony” data structure(可能作为 reset
包含在 C++23 中)。请注意,它不会追加:新元素以未指定的顺序重用已删除元素的空间。
元素 类型仍有待选择:您可以使用 std::hive
,一个类似的自定义类型,它知道 std::variant<A,B>
派生自 B
(以便更轻松地为客户提供 A
),或者您可以使用单独的容器方法(对排序有其自身的影响)。