清除标准容器而不是构造和析构它有意义吗?



假设我有一个函数:

void someFunc(void) {
std::vector<std::string> contentVector;
// here are some operations on the vector
}

函数被多次调用。profiler显示std::__u::vector::vectorstd::__u::vector::~vector的CPU使用率很高。

在函数外部创建向量并在函数开始时调用.clear()是否有意义?

其他标准容器也是同样的问题。

清除标准容器而不是构造和销毁它有意义吗?

是的,这是有道理的。这取决于你在做什么。使用任何适合用例的内容

在vector的情况下,您将重用存储,这在某些用例中可能会更好,因此请考虑这一点。

如果每次都重新创建vector(作为局部变量),那么vector每次都必须从堆中分配一个新的内部数组(如果您每次都向vector添加项而不首先调用reserve(),则如果vector的第一个分配的数组不够大,则vector可能不得不进行多次重新分配);然后,当方法调用返回时,vector的析构函数将从堆中释放内部分配的数组,以避免内存泄漏。

另一方面,如果您将vector保持在方法的外部,则vector的内部数组只需要分配一次(如果不调用reserve(),可能会重新分配几次),并且在以后的方法调用中调用clear()之后,相同的内部数组将被重用。

使用第二种方法将因此减少CPU周期的使用(没有固定的分配和从堆中取消分配,耶!),代价是在整个时间内使用一块额外的RAM分配(因为vector的内部数组将在整个时间内保持不变,并且将足够大,至少可以容纳到目前为止最坏情况下的项目数量)。用RAM使用来换取CPU能力是否值得,很大程度上取决于你在做什么,你的机器有多少RAM,它有多少CPU能力,等等,所以很难说哪种方法更好,除了"两种方法都试一试,衡量性能,选择你喜欢的方法"。

在函数的开头创建向量并调用.clear()有意义吗?

除非你保证没有并发调用。如果存在并发调用,在函数外部提升变量将是一场灾难。

甚至没有。一旦并发性引入到这个系统中,这可能是一场灾难。

要详细阐述的灾难:如果这是一个爬虫功能和读取不同的网站。在函数外使用相同的变量会将两个网站的内容混合为一个。

我的建议是将局部变量保留为local。除非contentVector总是保存一些数据。然后vector应该放在其他地方

这要视情况而定。

理想情况下,调用者应该尽可能少地了解函数的工作原理(封装)。如果调用者提供了矢量,那么如果调用者传递了错误的矢量,就有可能引入bug。而且,您使更改函数的实现成为一个痛苦的维护负担。函数越自包含越安全。

但是性能可能会受到影响,这时您可能会在性能关键部分(例如紧循环)中做出妥协。但是,可以有安全快速版本的函数,其中安全版本创建一个vector并将其传递给快速版本。

void some_function_fast_api(std::vector<std::string>& v) {
// here are some operations on the vector
}
inline void some_function_safe_api() {
std::vector<std::string> v;
some_function_fast_api(v);
}

相关内容

最新更新