为什么 std::vector::assign 不尽快释放现有分配的内存?

问题描述 投票:0回答:1

根据 cppreference

std::vector::assign
将内容替换为值
count
value
副本。 该定义意味着向量的现有状态未在
assign
中使用。

在以下示例代码中,在 GCC 14.2 上运行,

test1
打印
20000002
。 这表示分配新空间后现有内存将被删除。 通过适当放置
clear()
shrink_to_fit()
调用,
test2
减少峰值对象计数并打印
10000002

这是在实现

libstdc++
时错过了优化机会还是我对
std::vector
功能的理解不正确/不完整?

#include <iostream>
#include <vector>

int curr;
int max;

void update(int delta) { curr += delta; max = std::max(max, curr); }
void reset() { curr = max = 0; }

struct Foo {
    Foo() { update(1); }
    Foo(const Foo&) { update(1); }
    Foo& operator=(const Foo&) { return *this; }
    ~Foo() { update(-1); }
};

void test1() 
{
    reset();
    std::vector<Foo> foos;
    foos.assign(10'000'000, Foo{});
    foos.assign(10'000'001, Foo{});
    std::cout << max << '\n';
}

void test2() 
{
    reset();
    std::vector<Foo> foos;
    foos.assign(10'000'000, Foo{});
    foos.clear();
    foos.shrink_to_fit();
    foos.assign(10'000'001, Foo{});
    std::cout << max << '\n';
}

int main()
{
    test1();
    test2();
    return 0;
}
c++ stdvector libstdc++
1个回答
0
投票

我觉得有点混乱。您实际测量的是对构造函数和析构函数的调用量,而不是它使用的内存量。

在这种情况下,对

shrink_to_fit()
的调用没有任何意义,它只是保证对具有更大数量元素的
assign
进行底层重新分配。

观察到的 20mil 意味着有一个时刻,第二个

assign
创建了对象,但第一个
assign
的对象尚未删除。

事实上,第二个

assign
更大。因此,如果向量为第一个
assign
分配了确切数量的内存,那么对于第二个
assign
,它应该创建另一个内存块。它将创建第二对象负载,将
max
的值增加到2000万。

然后释放为前 1000 万个元素分配的内存。

不会提前释放第一个内存块,因为在构造第二个内存块的过程中可能会出现异常。 因此,当保证第二个内存块的分配和填充成功时,第一个内存块就被释放了。

© www.soinside.com 2019 - 2024. All rights reserved.