vector 释放内存 swap

本文介绍了C++ STL中swap算法及其在容器内存管理中的应用。不仅解析了泛型算法swap的功能,还展示了如何利用容器的swap成员函数实现内存的有效释放。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://blog.youkuaiyun.com/jerryjbiao/article/details/7389233


 相信大家看到swap这个词都一定不会感到陌生,甚至会有这样想法:这不就是简单的元素交换嘛。的确,swap交换函数是仅次于Hello word这样老得不能老的词,然而,泛型算法东风,这个小小的玩意儿却在C++ STL中散发着无穷的魅力。本文不仅详细地阐述STL泛型算法swap,并借助泛型算法这股东风,展现STL容器中swap成员函数的神奇魅力。注意哦,泛型算法swap和容器中的swap成员函数,这是两个不同角度和概念哦!

     一、泛型算法swap

      老规矩,我们先来看看swap的函数原型:

[cpp]  view plain copy
  1. template <class T> void swap ( T& a, T& b )  
  2. {  
  3.   T c(a); a=b; b=c;  
  4. }  
  5.    
      函数原型超级简单吧,这里我们就不做过多的解释啦,下面我们还是通过一个简单的示例来熟悉熟悉它的使用吧。

但是vector的swap成员函数是怎么实现的?

[cpp]  view plain  copy
  1. void swap(vector<_Tp, _Alloc>& __x) {  
  2.     __STD::swap(_M_start, __x._M_start);  
  3.     __STD::swap(_M_finish, __x._M_finish);  
  4.     __STD::swap(_M_end_of_storage, __x._M_end_of_storage);  
  5.   }  

仅仅是交换了指向的首尾指针和容量指针

      程序示例:

[cpp]  view plain copy
  1. /******************************************************************* 
  2.  * Copyright (C) Jerry Jiang 
  3.  *                
  4.  * File Name   : swap.cpp 
  5.  * Author      : Jerry Jiang 
  6.  * Create Time : 2012-3-24 4:19:31 
  7.  * Mail        : jbiaojerry@gmail.com 
  8.  * Blog        : http://blog.youkuaiyun.com/jerryjbiao  
  9.  *                
  10.  * Description : 简单的程序诠释C++ STL算法系列之十五                   
  11.  *               变易算法 : 元素交换swap    
  12.  *                
  13.  ******************************************************************/  
  14.   
  15. #include <iostream>  
  16. #include <algorithm>  
  17. #include <vector>  
  18. #include <iterator>  
  19.   
  20. using namespace std;  
  21.   
  22. int main ()   
  23. {  
  24.       
  25.     int x = 10, y = 20;                         // x:10 y:20  
  26.     swap(x, y);                              // x:20 y:10  
  27.       
  28.     vector<int> first (4, x), second (6, y);  // first:4x20 second:6x10  
  29.     swap(first, second);                     // first:6x10 second:4x20  
  30.       
  31.     cout << "first contains:";  
  32.     //使用一般的iterator方式输出first  
  33.     for (vector<int>::iterator it=first.begin();  it != first.end(); ++it)  
  34.     {  
  35.         cout << " " << *it;  
  36.     }  
  37.     cout << endl;  
  38.   
  39.     cout << "second contains: ";  
  40.     //使用copy()来实现second的输出  
  41.     copy(second.begin(), second.end(), ostream_iterator<int>(cout, " "));  
  42.     cout << endl;  
  43.       
  44.     return 0;  
  45. }  
          上面示例程序十分简单,只是为了巩固前文中copy算法的使用,我在程序中采用了两种方式进行输出,好了,泛型算法swap我们就不再废话了,现在我们来看看本文中的重头戏吧。

        二、容器中的成员函数swap

        在容器vector中,其内存占用的空间是只增不减的,比如说首先分配了10,000个字节,然后erase掉后面9,999个,则虽然有效元素只有一个,但是内存占用仍为10,000个。所有内存空间在vector析构时回收。

     一般,我们都会通过vector中成员函数clear进行一些清除操作,但它清除的是所有的元素,使vector的大小减少至0,却不能减小vector占用的内存。要避免vector持有它不再需要的内存,这就需要一种方法来使得它从曾经的容量减少至它现在需要的容量,这样减少容量的方法被称为“收缩到合适(shrink to fit)”。(节选自《Effective STL》)如果做到“收缩到合适”呢,嘿嘿,这就要全仰仗“Swap大侠”啦,即通过如下代码进行释放过剩的容量:

[cpp]  view plain copy
  1. vector< T >().swap(X)  
        下面我们通过一个简单的示例来show一下:

[cpp]  view plain copy
  1. /******************************************************************* 
  2.  * Copyright (C) Jerry Jiang 
  3.  *                
  4.  * File Name   : swap.cpp 
  5.  * Author      : Jerry Jiang 
  6.  * Create Time : 2012-3-24 4:19:31 
  7.  * Mail        : jbiaojerry@gmail.com 
  8.  * Blog        : http://blog.youkuaiyun.com/jerryjbiao  
  9.  *                
  10.  * Description : 简单的程序诠释C++ STL算法系列之十五                   
  11.  *               成员函数swap实现容器的内存释放    
  12.  *                
  13.  ******************************************************************/  
  14.   
  15. #include <iostream>  
  16. #include <algorithm>  
  17. #include <vector>  
  18. #include <iterator>  
  19.   
  20. using namespace std;  
  21.   
  22. int main ()   
  23. {  
  24.     int x = 10;  
  25.     vector<int> myvector(10000, x);    
  26.   
  27.     //这里打印仅仅是元素的个数不是内存大小  
  28.     cout << "myvector size:"  
  29.          << myvector.size()  
  30.          << endl;  
  31.   
  32.     //swap交换函数释放内存:vector<T>().swap(X);  
  33.     //T:int ; myvertor代表X  
  34.     vector<int>().swap(myvector);  
  35.   
  36.     //两个输出仅用来表示swap前后的变化  
  37.     cout << "after swap :"  
  38.          << myvector.size()  
  39.          << endl;  
  40.   
  41.     return 0;  
  42. }  
swap交换技巧实现内存释放思想:vector()使用vector的默认构造函数建立临时vector对象,再在该临时对象上调用swap成员,swap调用之后对象myvector占用的空间就等于一个默认构造的对象的大小,临时对象就具有原来对象v的大小,而该临时对象随即就会被析构,从而其占用的空间也被释放。

std::vector<T>().swap(X)

作用相当于:

{

std::vector<T>  temp(X);

temp.swap(X);

}


可以用类似的方法实现vector和string的适当收缩

[cpp]  view plain  copy
  1. vector<int> vec(100000, 0);  
  2. for (int i = 0; i < 100000-2; ++i) vec.pop_back();  
  3. cout << vec.capacity() <<endl;  
  4. vector<int>(vec).swap(vec);  
  5. cout << vec.capacity() << endl;  
<think>好的,用户现在的问题是“vector彻底释放内存”。我需要详细解释如何让std::vector完全释放其占用的内存。首先,我应该回忆vector内存管理机制。vector的容量(capacity)不会自动缩减,即使元素被清除(如clear()),因为capacity是为了避免频繁重新分配内存而设计的。要彻底释放内存,可能需要用到shrink_to_fit()方法,或者通过交换空vector的技巧(swap trick)。 首先,用户可能想知道为什么clear()不够。因为clear()只是销毁元素,调用析构函数,但不会释放内存,capacity保持不变。所以需要进一步操作。 然后,shrink_to_fit()是C++11引入的方法,它会请求容器缩减capacity以匹配size。但这是一个请求,标准允许实现不严格遵守,但大多数现代编译器会执行。而swap trick则是通过与一个空vector交换,这样原vector的capacity会被置为0(或空vector的capacity,通常为0),从而释放内存。 需要解释这两种方法的区别和适用场景。比如,shrink_to_fit()更简洁,但可能不保证;swap trick更可靠,但代码稍多。 还要注意,vector的析构函数会释放所有内存,所以如果vector是局部变量,离开作用域时会自动释放。但用户可能指的是在不销毁vector对象的情况下释放内存。 另外,需要提到成员函数shrink_to_fit()的行为,以及swap的具体实现。例如,std::vector<T>().swap(vec)会创建一个临时空vector,与原vector交换内容,这样原vector的capacity会变成临时vector的capacity(通常为0),而临时vector在语句结束后销毁,带走原来的内存。 可能还需要讨论不同编译器的实现差异,比如某些情况下shrink_to_fit()可能不会完全释放,但swap trick更可靠。 还要注意,对于C++11之前,没有shrink_to_fit(),只能用swap trick。 最后,给出示例代码,展示clear()、shrink_to_fit()swap trick的效果对比,并说明何时使用哪种方法。 需要确保回答准确,涵盖关键点,并解答用户可能的疑惑,比如为什么需要这些方法,以及它们的局限性。 </think>在C++中,`std::vector` 的内存管理遵循“**容量(capacity)与大小(size)分离**”的原则:即使通过 `clear()` 清空元素(`size` 变为0),其底层分配的内存(`capacity`)通常不会自动释放。若需**彻底释放内存**,需显式触发内存回收操作。以下是具体方法及原理: ### 一、关键概念:`size` 与 `capacity` - `size`:当前容器中实际存储的元素数量(调用 `clear()` 后 `size` 变为0)。 - `capacity`:容器底层已分配的内存可容纳的最大元素数量(`capacity ≥ size`)。 - **核心矛盾**:`clear()` 仅销毁元素(调用析构函数),但不会释放底层内存(`capacity` 不变),目的是避免后续插入元素时频繁重新分配内存。 ### 二、彻底释放内存的方法 #### 方法1:`shrink_to_fit()`(C++11及以上) `shrink_to_fit()` 是标准库提供的成员函数,用于请求容器将 `capacity` 缩减至 `size` 的大小(即释放多余内存)。其行为是“**非强制性**”的(标准允许实现保留额外内存),但现代编译器(如GCC、Clang)通常会执行实际的内存释放。 **适用场景**:希望容器在清空后尽可能减少内存占用,但允许编译器保留少量优化空间。 **示例**: ```cpp #include <vector> #include <iostream> int main() { std::vector<int> vec(1000); // size=1000, capacity=1000 vec.clear(); // size=0, capacity=1000(内存释放) std::cout << "Before shrink: capacity = " << vec.capacity() << std::endl; // 输出1000 vec.shrink_to_fit(); // 请求缩减capacity至size(即0) std::cout << "After shrink: capacity = " << vec.capacity() << std::endl; // 输出0(常见实现) return 0; } ``` #### 方法2:交换技巧(Swap Trick)(C++03及以上) 通过与一个空 `vector` 交换内容,强制释放原 `vector` 的内存。该方法利用了临时对象的生命周期特性,**确保内存被彻底释放**(不受编译器实现限制)。 **原理**: - 临时空 `vector` 的 `capacity` 为0(或极小值)。 - 交换后,原 `vector` 的 `capacity` 变为临时对象的 `capacity`(通常为0),而临时对象在语句结束后销毁,带走原 `vector` 的底层内存。 **示例**: ```cpp #include <vector> #include <iostream> int main() { std::vector<int> vec(1000); // size=1000, capacity=1000 vec.clear(); // size=0, capacity=1000 // 交换技巧:与空vector交换 std::vector<int>().swap(vec); // 临时空vector与vec交换,vec的capacity变为0 std::cout << "After swap: capacity = " << vec.capacity() << std::endl; // 输出0 return 0; } ``` ### 三、注意事项 1. **析构函数自动释放内存**: 若 `vector` 是局部变量,离开作用域时会调用析构函数,**彻底释放所有内存**(包括 `capacity` 对应的内存)。例如: ```cpp void func() { std::vector<int> vec(1000); // 分配内存 } // func结束,vec析构,内存自动释放 ``` 2. **`shrink_to_fit()` 的局限性**: 标准未强制要求 `shrink_to_fit()` 必须释放所有多余内存(例如,某些编译器可能保留少量内存用于优化后续插入操作)。若需严格释放,应使用交换技巧。 3. **元素类型的影响**: 若 `vector` 存储的是自定义类型(含资源管理,如 `std::string`),`clear()` 会调用元素的析构函数释放其内部资源(如字符串的动态内存),但 `vector` 自身的 `capacity` 内存仍需通过上述方法释放。 ### 四、总结 - 若需**彻底释放 `vector` 底层内存**,推荐使用交换技巧(`std::vector<T>().swap(vec)`),适用于所有C++版本且行为确定。 - 若使用C++11及以上,且接受编译器的非强制优化,可使用 `shrink_to_fit()`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值