【问题标题】:Manage memory on vector assignment管理向量分配的内存
【发布时间】:2017-01-23 15:21:47
【问题描述】:

(这个问题可以扩展到其他容器)

我可以使用向量来存储大量数据,那么如果我没有很多内存,那么了解 c++ 如何管理对这个容器的分配非常重要。

a) 当对返回向量的函数进行分配时,该向量上的数据会在分配后立即清理,还是保留到最后一刻才能接收新数据?

b) 如果数据被立即销毁,函数过程中哪个状态向量来构建新数据?

b.1)如果数据保留了,这意味着我可以在内存中拥有两个巨大的向量(旧数据和新数据),直到分配(返回)?

c) 那么移动语义呢?它试图使用已经创建的空间? (如果数据没有像第一个问题那样立即销毁)

为了更好地演示,我写了一个小程序:

#include <vector>
#include <string>

using namespace std;

vector<string> func2() {
    vector<string> f2(200000, string(20,'a'));
    return f2;
}

vector<string> func4() {
    vector<string> f4(400000, string(40,'b'));
    //Now I have in memory 400000X40 + 200000X20?
    return f4;
    //after assignment I know I have just f4 content
}

vector<string> func1() {
    vector<string> f1(100000, string(10,'c'));
    return f10;
}

int main() {
    vector<string> mVec;

    mVec = func2(); //Create internally a vector with 20 units string with 20 'b' inside

    mVec = func4(); //Create internally a vector with 40 units string with 40 'b' inside

    mVec = func1(); //Create internally a vector with 10 units string with 10 'b' inside

    return 0;
}

如果移动语义确实使用了现有空间,当 mVec 数据较少且需要分配更多(func2 到 func4)或反之(func4 到 func1)时,它是如何工作的。

【问题讨论】:

  • mVec = func2() 使用移动赋值;函数内部f2分配的内部数据存储交给mVec。不执行进一步的分配或复制。与mVec = func4() 相同——存储在函数内部分配,然后交给mVec;后者在接受新数据的所有权之前释放其先前的数据。与mVec = func1() 相同。
  • 一种更有效的方法可能是通过引用函数来传递向量。这可能会消除一些向量的复制(取决于优化设置和编译器)。

标签: c++ vector containers


【解决方案1】:

当调用 func4() 时,在 return 语句之前,你肯定有两个大向量。直到分配点,你都记得它们。

至于c),vector是contigous container,所以当你创建新vector时,它会作为一个整体存储在内存中,而不是一部分在内存块1,另一部分在内存块127(只是一个例子) .

我的建议是,通过引用使用传递向量(将被重新归档),并在填充之前正确调整它的大小,这样您就可以避免分配整个向量。

代码示例(优化建议):

#include <vector>
#include <algorithm>    // std::fill
#include <string>

using namespace std;

void func2(vector<string>& vec) {
    vec.resize(200000);
    fill(vec.begin(), vec.end(), string(20, 'a'));
}

void func4(vector<string>& vec) {
    vec.resize(400000);
    fill(vec.begin(), vec.end(), string(40, 'b'));
}

void func1(vector<string>& vec) {
    vec.resize(100000);
    fill(vec.begin(), vec.end(), string(10, 'c'));
}

int main() {
    vector<string> mVec;

    func2(mVec); //Create internally a vector with 20 units string with 20 'b' inside

    func4(mVec); //Create internally a vector with 40 units string with 40 'b' inside

    func1(mVec); //Create internally a vector with 10 units string with 10 'b' inside

    return 0;
}

【讨论】:

    猜你喜欢
    • 2012-06-08
    • 1970-01-01
    • 2021-08-31
    相关资源
    最近更新 更多