【c++隨筆16】reserve之后,使用std::copy會崩潰?
- 一、reserve之后,使用std::copy會崩潰?
- 二、函數std::reserve、std::resize、std::copy
- 1、std::resize:
- 2、std::reserve:
- 3、std::copy:
- 三、崩潰原因分析
- 方案1、你可以使用 std::back_inserter 插入迭代器來向 destination 中插入元素,代碼如下:
- 方案2、resize將容器大小調整同時,新增的元素將會被默認初始化為0,這樣std::copy中的destination.begin()就可用訪問到元素了
原創作者:鄭同學的筆記
原創地址:https://zhengjunxue.blog.csdn.net/article/details/134272501
一、reserve之后,使用std::copy會崩潰?
先看代碼
#include <iostream>
#include <vector>
#include <algorithm>int main() {std::vector<int> source = { 1, 2, 3, 4, 5 };std::vector<int> destination;// 在目標vector中預留足夠的空間,避免不必要的重新分配destination.reserve(source.size());// 使用std::copy將source中的元素復制到destination中std::copy(source.begin(), source.end(), destination.begin());// 打印復制后的destination內容for (int num : destination) {std::cout << num << " ";}std::cout << std::endl;return 0;
}
運行,崩潰截圖如下
我們先簡單說下std::reserve、std::resize、std::copy三個函數的用法,然后再說崩潰的原因。
二、函數std::reserve、std::resize、std::copy
1、std::resize:
- std::resize 用于改變容器的大小,并可以指定新元素的初值。
- 如果新的大小大于當前大小,則在末尾添加新元素;如果新的大小小于當前大小,則刪除多余的元素。
- 使用 resize 會改變容器內的元素個數,并可能導致元素值的改變。
示例代碼如下:
std::vector<int> vec = {1, 2, 3};
vec.resize(5); // 將容器大小調整為 5,新增的元素將會被默認初始化為0
vec.resize(3); // 將容器大小調整為 3,多余的元素將會被刪除
2、std::reserve:
- std::reserve 用于預留容器的空間,但不會改變容器的大小。
- 當你知道容器將要存儲大量元素時,可以使用 reserve 來提前分配足夠的內存,避免容器多次擴張操作。
- 使用 reserve 不會改變容器中的元素個數,只是預分配了足夠的空間。
示例代碼如下:
std::vector<int> vec;
vec.reserve(100); // 預留至少能容納100個元素的空間
3、std::copy:
template <class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result);
std::copy 用于將一個范圍內的元素復制到另一個范圍,它可以用于將一個容器中的元素復制到另一個容器中
注意事項
- 確保輸出范圍有足夠的空間來容納被復制的元素,否則可能會導致未定義的行為。
- 當處理容器時,確保輸出容器有足夠的容量,或者使用插入迭代器(如 std::back_inserter)來確保動態分配足夠的空間。
int source[] = {1, 2, 3, 4, 5};
int destination[5];// 使用 std::copy 將 source 數組的內容復制到 destination 數組
std::copy(std::begin(source), std::end(source), std::begin(destination));
三、崩潰原因分析
-
在這個代碼中,當你使用 std::copy 將 source 中的元素復制到 destination 中時,會導致程序崩潰的原因是因為 destination 容器的空間雖然預留了,但是其中并沒有實際的元素,所以無法直接通過 destination.begin() 來訪問 destination 的首個元素。
-
在使用 std::copy 進行復制時,目標容器必須有足夠的空間來容納被復制的元素,并且使用 std::back_inserter 或者確保目標容器大小與源容器相同的方式來進行插入操作。如果目標容器沒有足夠的空間或者沒有正確的插入迭代器,就會導致未定義的行為,可能導致程序崩潰。
要修復這個問題,有兩個方法你可以使用
方案1、你可以使用 std::back_inserter 插入迭代器來向 destination 中插入元素,代碼如下:
#include <iostream>
#include <vector>
#include <algorithm>int main() {std::vector<int> source = { 1, 2, 3, 4, 5 };std::vector<int> destination;// 在目標vector中預留足夠的空間,避免不必要的重新分配destination.reserve(source.size());// 使用std::copy將source中的元素復制到destination中std::copy(source.begin(), source.end(), std::back_inserter(destination));// 打印復制后的destination內容for (int num : destination) {std::cout << num << " ";}std::cout << std::endl;return 0;
}
方案2、resize將容器大小調整同時,新增的元素將會被默認初始化為0,這樣std::copy中的destination.begin()就可用訪問到元素了
#include <iostream>
#include <vector>
#include <algorithm>int main() {std::vector<int> source = { 1, 2, 3, 4, 5 };std::vector<int> destination;// 在目標vector中預留足夠的空間,避免不必要的重新分配destination.resize(source.size());// 使用std::copy將source中的元素復制到destination中std::copy(source.begin(), source.end(), destination.begin());// 打印復制后的destination內容for (int num : destination) {std::cout << num << " ";}std::cout << std::endl;return 0;
}