C++ - 覆盖/重建整个 std::vector 的最佳实践

C++ - Best practice for overwriting/reconstructing entire std::vector

本文关键字:vector 最佳 std 覆盖 重建 C++      更新时间:2023-10-16

如果我有一个 std::vector,我想完全覆盖(而不仅仅是调整大小)。在内存管理方面,最安全的方法是什么?例如

int main() {
    std::vector<float> X (5, 5.0);
    X = std::vector<float> (6, 6.0);
    X = std::vector<float> (4, 4.0);
}

将创建一个值为 5.0 的 5 个浮点数的向量。然后它将用值为 6.0 的大小为 6 的向量覆盖它,然后用值为 4.0 的大小的向量覆盖。如果我无限期地执行此类操作,则此方法是否存在损坏或泄漏内存的风险?我应该在每次覆盖之前使用clear()吗?有没有更有效的方法来实现这一目标?

我相信这个问题已经被问了很多次,但谷歌并没有拉出我正在寻找的确切场景。

谢谢!

std::vector具有特定的成员函数来执行此操作。分配器和复制/移动,vector的每个构造函数都有一个相应的重载assign做同样的事情。因此,如果您想重用vector的存储,只需使用它:

std::vector<float> X (5, 5.0);
X.assign(6, 6.0);
X.assign(4, 4.0);

当然,不能保证vector实现不会重新分配内存。但是,这将是一个非常愚蠢的实现。

这种方法是否存在损坏或泄漏内存的风险?

不。

我应该在每次覆盖之前使用clear()吗?

没必要。

有没有更有效的方法来实现这一目标?

这在很大程度上取决于您不断替换向量的模式。在当前代码中,分配一个新向量,然后释放旧向量,每次都将新向量移动到X中。

分配

和解除分配是成本高昂的操作。循环向量并更改每个现有元素和/或将新元素推送到现有向量中可能是一个更好的主意。大致如下:

std::vector<float> X (5, 5.0);
std::transform(begin(X), end(X), begin(X), [](int){ return 6.0; }); 
X.resize(6, 6.0);
std::transform(begin(X), end(X), begin(X), [](int){ return 4.0; }); 
X.resize(4);

如果元素数很大并且对象不是简单的整数,这可能会导致代码变慢。

检查这一点的最好方法是实际编写两个版本并对其进行基准测试。