【发布时间】:2021-08-05 06:33:28
【问题描述】:
我需要什么
我需要一个容器来存储对象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的元素?然后我可以包装一个指针向量并规避分散内存的问题。
【问题讨论】:
-
std::vector< std::unique_ptr< A > >怎么样? -
@RichardCritten 不会因为内存分散而导致问题吗? (见问题)
-
对此我不是 100% 确定,但我想我已经得到了关于保留内存部分的答案。您可以保留相当大的内存块,然后使用
placement-new就地构造一个元素:en.cppreference.com/w/cpp/language/new -
考虑到需求我宁愿推荐
std::deque而不是std::vector。也使用emplace函数而不是push。 -
关于性能 - 让它工作 - 测量 - 优化。
标签: c++ iterator containers subclass stdvector