C++ 如何将std::vector的容量限制为元素数

C++ 如何将std::vector的容量限制为元素数,c++,c++11,memory,memory-management,vector,C++,C++11,Memory,Memory Management,Vector,我的程序使用569MB内存,只需要使用500MB, 我有很多不同大小的std::vector 有没有办法将容量设置为元素数,以避免内存开销。 我不关心性能,内存是关键您可能正在寻找“收缩到拟合”方法,请参阅 或者,如果您不能/不允许使用C++11,您可能希望使用交换来适应习惯用法: 在C++11中,请注意,编译器可能会忽略收缩到拟合: vector<int> v; // ... v.shrink_to_fit(); 交换适应习惯用法: vector<int> v; /

我的程序使用569MB内存,只需要使用500MB, 我有很多不同大小的std::vector 有没有办法将容量设置为元素数,以避免内存开销。
我不关心性能,内存是关键

您可能正在寻找“收缩到拟合”方法,请参阅

或者,如果您不能/不允许使用C++11,您可能希望使用交换来适应习惯用法:

在C++11中,请注意,编译器可能会忽略收缩到拟合:

vector<int> v;
// ... 
v.shrink_to_fit();
交换适应习惯用法:

vector<int> v;
// ...
vector<int>( v ).swap(v);
// v is swapped with its temporary copy, which is capacity optimal
如何将std::vector的容量限制为元素数

您所能做的最好的事情是在添加元素之前保留所需的空间。这也应该有最好的性能,因为它不会导致重新分配和复制

如果这不实用,那么可以在添加元素后使用std::vector::shrink_进行拟合。当然,如果分配的峰值可能永远不会超过设定的限制,那么这也无济于事


从技术上讲,这两种方法都不能保证容量与尺寸相匹配。您依赖于标准库实现的行为。

在将任何内容推送到向量之前,请编写一些包装器并控制向量的大小,或者改用固定大小的std::array

您可以使用自定义分配器并将所需的容量提供给模板参数。修改此线程中的示例:


但是,访问超出范围的索引时应谨慎

不保证有效,您可以使用“收缩到拟合C++11”函数使向量刚好足够大以容纳数据。如果该函数有帮助,您可以尝试。boost是选项吗?然后使用@Paulstellian:在这里可能太晚了。如果程序限制为500 MB,操作系统可能会终止进程或拒绝内存分配。当向量变得太大时,后者将变成std::bad_alloc。v.reserven保证向量能够容纳至少n个元素,但容量可能大于n c++17 23.3.11.3.3,因此根本不能保证避免超负荷。就我对23.3.11.3.9的理解而言,即使收缩到适合也不能保证大小=之后的容量…@Aconcagua很好的观点,我认为在调用新向量的reserve时有一个保证,但显然我错了。似乎无法保证容量与向量大小匹配。我改变了我的答案,以反映在该标准下,也不能保证新字符[1000]不会分配gb,因此独特的ptr方法不能保证没有开销。@Yakk-oh-day。我相信你的话。那么,动态内存并没有多少保证,是吗?就我所见,没有办法使向量的容量等于它的大小。数组是这样做的,但您需要在编译时知道最终大小,因为大小是一个模板参数,不能修改大小。如果出现最坏的情况,您可能不得不退回到旧的c++11之前的阵列。不太好,但如果最终大小在编译时未知,我看不到另一种保证大小约束的方法。。。
#include <memory>
#include <iostream>
#include <vector>
namespace my_allocator_namespace
{
    template <typename T, size_t capacity_limit>
    class my_allocator: public std::allocator<T>
    {
    public:
        typedef size_t size_type;
        typedef T* pointer;
        typedef const T* const_pointer;

        template<typename _Tp1 >
        struct rebind
        {
            typedef my_allocator<_Tp1 , capacity_limit> other;
        };

        pointer allocate(size_type n, const void *hint=0)
        {
            if( n  > capacity_limit ) {
                return std::allocator<T>::allocate(capacity_limit ); 
            }
            return std::allocator<T>::allocate(n, hint);
        }

        void deallocate(pointer p, size_type n)
        {
            return std::allocator<T>::deallocate(p, n);
        }

        my_allocator() throw(): std::allocator<T>() {  }
        my_allocator(const my_allocator &a) throw(): std::allocator<T>(a) { }
        template <class U,size_t N>                    
        my_allocator(const my_allocator<U,N> &a) throw(): std::allocator<T>(a) { }
        ~my_allocator() throw() { }
    };
}
using namespace std;
using namespace my_allocator_namespace;
int main(){
vector<int, my_allocator<int,20> > int_vec(10);
    for(int i = 0 ;i < 20; i++)
    {
        std::cerr << i << "," << int_vec.size() << std::endl;
        int_vec.push_back(i);
    }
}