简体   繁体   English

为什么 std::vector::operator= 会过度分配内存?

[英]Why does std::vector::operator= overallocate memory?

I am investigating a case where way more memory is consumed than needed.我正在调查一个案例,其中消耗的内存比需要的多。 If I assign a string to an std::vector , it suddenly reserves more heap memory than needed, even though the size of the string is already known:如果我将一个字符串分配给std::vector ,它会突然保留比所需更多的堆内存,即使字符串的大小已经知道:

Here's what I broke it down to:这是我将其分解为:

#include <vector>
#include <iostream>
#include <new>

void* operator new(size_t size) { 
    void * p = malloc(size); 
    std::cout << "\talloc " << size << " @ " << p; 
    return p;
} 

void operator delete(void* p) { 
    std::cout << "\t      free " << p; 
    free(p);
} 

int main() {
    {
        std::cout << std::endl << "1. Create first string:   ";
        auto s1 = std::string{"String with 20 chars"};

        std::cout << std::endl << "2. Create longer string:  ";
        auto s2 = std::string{"String with 25 characters"};

        std::cout << std::endl << "3. Copy construct:        ";
        auto s3 = s2;

        std::cout << std::endl << "4. Copy assign:           ";
        s1 = s3;

        std::cout << std::endl << "5. Leaving scope:         ";
    }
    std::cout << std::endl;
}

Result:结果:

1. Create first string:     alloc 21 @ 0x56047f176280
2. Create longer string:    alloc 26 @ 0x56047f1762a0
3. Copy construct:          alloc 26 @ 0x56047f1762d0
4. Copy assign:             alloc 41 @ 0x56047f176300         free 0x56047f176280
5. Leaving scope:                 free 0x56047f1762d0         free 0x56047f1762a0         free 0x56047f176300

I would expect line 4 to be the same as line 3.我希望第 4 行与第 3 行相同。

Why do both libstdc++ (this result) and libc++ (32/48 bytes) allocate more memory for a copy assignment than for a copy construction?为什么 libstdc++(这个结果)和 libc++(32/48 字节)为复制赋值分配的内存比为复制构造分配的内存多? In both cases, the new size is known.在这两种情况下,新的大小都是已知的。 I can't see how one of those is more likely to require additional memory in the future.我看不出其中之一在未来更有可能需要额外的内存。

I tracked it down in the basic_string implementation of libstdc++.我在 libstdc++ 的 basic_string 实现中找到了它。 operator=(const basic_string&) calls this->assign , which calls _M_assign , which calls _M_create with the new (minimal) and the old capacity. operator=(const basic_string&)调用this->assign ,后者调用_M_assign ,后者使用新(最小)和旧容量调用_M_create Here, the original capacity is doubled.在这里,原始容量增加了一倍。 A link to the exponential growth policy is included as a comment.指数增长政策的链接包含在评论中。

First, I did not understand how this is related to my example.首先,我不明白这与我的例子有什么关系。 After all, I just want to replace a value.毕竟,我只想替换一个值。

The growth policy for operator=(const basic_string&) makes more sense when, instead of a single assignment, you consider this code:当您考虑以下代码而不是单个赋值时, operator=(const basic_string&)的增长策略更有意义:

std::string s;
for (auto i = 100; i < 110; ++i) s = s + std::to_string(i);

Here, setting the capacity so that it is "just fitting" would violate the linear growth requirement.在这里,将容量设置为“恰到好处”将违反线性增长要求。

To solve the memory consumption problem, I now call shrink_to_fit() on the target string.为了解决内存消耗问题,我现在在目标字符串上调用shrink_to_fit()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么std :: vector需要operator = - Why std::vector requires operator = 为什么std :: vector零会初始化其内存? - Why does std::vector zero initilize its memory? 为什么std :: hex会导致内存损坏vector.size()? - Why does std::hex lead to memory corruption vector.size()? 为什么std :: vector :: operator []比std :: vector :: at()快5到10倍? - Why is std::vector::operator[] 5 to 10 times faster than std::vector::at()? std::vector 在内存中是什么样子的? - What does std::vector look like in memory? 为什么需要std :: move来调用std :: vector的move assign运算符 - Why std::move is required to invoke move assign operator of std::vector 为什么为 const std::vector 定义了 operator[],而不为 const std::map 定义了 operator[]? - Why is operator[] defined for const std::vector, but not for const std::map? 在 C++20 中 std::vector 运算符 == 对具有不同分配器的向量不起作用有什么原因吗? - Is there a reason why in C++20 std::vector operator == does not work for vectors with different allocators? 为什么不为std :: vector重载operator + =()? - Why not overload operator+=() for std::vector? std :: vector在哪里分配其内存? - Where does a std::vector allocate its memory?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM