(C++基础_STL) —— vector 类的基本应用

文章目录

  • (C++基础_STL) —— vector类的基本应用
    • 0 个人介绍
    • vector容器
      • 1. vector的基本概念
      • 2. vector的构造函数
      • 3. vector的赋值操作
      • 4. vector的容量和大小
      • 5. vector插入与删除
      • 6. vector数据存取
      • 7. vector的交换(Swap)
      • 8. vector预先开辟容量(Reverse)
    • 个人格言

(C++基础_STL) —— vector类的基本应用

     在日常的C++开发过程中,我们会经常使用到STL最为赋能加速开发的一个基本库,那么在有一定的C++的语言的基础上,学习如何使用STL是一件非常有益与后续有益于自己面对更加复杂的需求和日常开发赋能的,因此,本人虽然工作了有一段时日了,准备开始写一系列专栏记录自己重温STL的一些用法,并加深自己对于STL的理解和运用的过程,本系列文章主要用于自己复习和参考使用,如果您看到感兴趣了也可以跟我一并一起进一步学习和探讨。

     个人编写的项目地址如下:UsingSTLEx

0 个人介绍

作者: 赵萱婷
简介: 一个在工业软件领域摸爬滚打的新人,毕业于华科软院的一个普通人,希望未来能够在工业设计软件领域深耕越走越远的软件工程师。
个人格言:用心去感受你自己需要坚持的生活,未来慢慢会给你答案的。
知乎:https://www.zhihu.com/people/Tom_Zhao
STL项目地址: https://gitee.com/zhaotianyuCoding/using-stlex

vector容器

1. vector的基本概念

     基础功能:

  • vector数据结构和数组非常相似,也称为单端数组。

     vector与普通数组区别:

  • 不同之处在于数组是静态空间,而vector可以动态扩展。

     所谓的动态扩展:

  • 并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间。

(C++基础_STL) —— vector 类的基本应用_第1张图片

2. vector的构造函数

     vector的构造函数主要用于创建vector容器本身,只是会存在不同的集中创建方式,具体的函数原型有如下一些:

  • vector v; //采用模板实现类实现,默认构造函数
  • vector(v.begin(), v.end()); //将v[begin(), end())区间中的元素拷贝给本身。
  • vector(n, elem); //构造函数将n个elem拷贝给本身。
  • vector(const vector &vec); //拷贝构造函数。

     具体相关项目的CMakeLists.txt如下:

#[================================================================[.rst:
    Copyright (c)2021, Tom Zhao personal. ("UsingSTLEx")
    This software is a personal tools project by Tom Zhao.
    Description:
#]================================================================]

set(TZ_MAIN_NAME VectorConstructor)

set(TZ_MAIN_INCLUDE

)

set(TZ_MAIN_INC

)

set(TZ_MAIN_SRC
	main.cpp
)

add_executable(${TZ_MAIN_NAME}
	${TZ_MAIN_INCLUDE}
	${TZ_MAIN_INC}
	${TZ_MAIN_SRC}
)

set_property(TARGET ${TZ_MAIN_NAME} PROPERTY FOLDER "UsingVector")

     具体相关项目的代码如下,放在VectorConstrutor项目里面:


///
// Copyright (c) 2021, Tom Zhao personal. ("UsingSTLEx")
// This software is a personal tools project by Tom Zhao.
// Description:
///

#include 
#include 

using namespace std;

// print the vector for show.
void printVector(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}

void TzVectorConstructorCase01()
{
	vector<int> v1; // constructor without any param.
	for (int i = 0; i < 10; i++) {
		v1.push_back(i);
	}
    
	printVector(v1);

    // constructor with param with a certain vector's start and end.
	vector<int> v2(v1.begin(), v1.end());
	printVector(v2);

    // constructor with param with range.
	vector<int> v3(10, 100);
	printVector(v3);
	
    // constructor with param with a certain vector.
	vector<int> v4(v3);
	printVector(v4);
}

int main(int argc, char *argv[])
{
	TzVectorConstructorCase01();

	system("pause");
	return 0;
}

3. vector的赋值操作

     赋值操作的主要作用是给已有的vector容器进行赋值或者直接覆盖的操作,具体可能用到的函数原型有:

  • vector& operator=(const vector &vec);//重载等号操作符

  • assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身。

  • assign(n, elem); //将n个elem拷贝赋值给本身。

     对于赋值操作个人所编写的示例如下:

CMakeLists:

#[================================================================[.rst:
    Copyright (c)2021, Tom Zhao personal. ("UsingSTLEx")
    This software is a personal tools project by Tom Zhao.
    Description:
#]================================================================]

set(TZ_MAIN_NAME VectorOperator)

set(TZ_MAIN_INCLUDE

)

set(TZ_MAIN_INC

)

set(TZ_MAIN_SRC
	main.cpp
)

add_executable(${TZ_MAIN_NAME}
	${TZ_MAIN_INCLUDE}
	${TZ_MAIN_INC}
	${TZ_MAIN_SRC}
)

set_property(TARGET ${TZ_MAIN_NAME} PROPERTY FOLDER "UsingVector")

     所对应的代码在VectorOperator项目中,具体的代码如下:


///
// Copyright (c) 2021, Tom Zhao personal. ("UsingSTLEx")
// This software is a personal tools project by Tom Zhao.
// Description:
///

#include 
#include 

using namespace std;

void printVector(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}

// operator=
void TzVectorOperatorCase01()
{
	vector<int> v1;
	for (int i = 0; i < 10; i++) {
		v1.push_back(i);
	}
    
	printVector(v1);

	vector<int>v2;
	v2 = v1;
	printVector(v2);

	vector<int>v3;
	v3.assign(v1.begin(), v1.end());
	printVector(v3);

	vector<int>v4;
	v4.assign(10, 100);
	printVector(v4);
}

// other operators.
void TzVectorOperatorCase02()
{
	std::vector<int> alice{1, 2, 3};
    std::vector<int> bob{7, 8, 9, 10};
    std::vector<int> eve{1, 2, 3};
 
    std::cout << std::boolalpha;
 
    // Compare non equal containers
    std::cout << "alice == bob returns " << (alice == bob) << '\n';
    std::cout << "alice != bob returns " << (alice != bob) << '\n';
    std::cout << "alice <  bob returns " << (alice < bob) << '\n';
    std::cout << "alice <= bob returns " << (alice <= bob) << '\n';
    std::cout << "alice >  bob returns " << (alice > bob) << '\n';
    std::cout << "alice >= bob returns " << (alice >= bob) << '\n';
 
    std::cout << '\n';
 
    // Compare equal containers
    std::cout << "alice == eve returns " << (alice == eve) << '\n';
    std::cout << "alice != eve returns " << (alice != eve) << '\n';
    std::cout << "alice <  eve returns " << (alice < eve) << '\n';
    std::cout << "alice <= eve returns " << (alice <= eve) << '\n';
    std::cout << "alice >  eve returns " << (alice > eve) << '\n';
    std::cout << "alice >= eve returns " << (alice >= eve) << '\n';
}

int main()
{
	TzVectorOperatorCase01();
	TzVectorOperatorCase02();

	system("pause");
	return 0;
}

     对于赋值操作,常用的还是直接使用=,用assign的方式可能比较少。

4. vector的容量和大小

     对于容量和大小,主要是用来操作和获取当前vector容器能够容纳多少个项目和具体现在拥有多少个项的大小的,具体使用到的相关函数的原型如下:

  • empty(); //判断容器是否为空

  • capacity(); //容器的容量

  • size(); //返回容器中元素的个数

  • resize(int num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。//如果容器变短,则末尾超出容器长度的元素被删除。

  • resize(int num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。​ //如果容器变短,则末尾超出容器长度的元素被删除

     对应项目的CMakeLists文件如下:

#[================================================================[.rst:
    Copyright (c)2021, Tom Zhao personal. ("UsingSTLEx")
    This software is a personal tools project by Tom Zhao.
    Description:
#]================================================================]

set(TZ_MAIN_NAME VectorCapacity)

set(TZ_MAIN_INCLUDE

)

set(TZ_MAIN_INC

)

set(TZ_MAIN_SRC
	main.cpp
)

add_executable(${TZ_MAIN_NAME}
	${TZ_MAIN_INCLUDE}
	${TZ_MAIN_INC}
	${TZ_MAIN_SRC}
)

set_property(TARGET ${TZ_MAIN_NAME} PROPERTY FOLDER "UsingVector")

     该项目代码叫VectorCapacity,可以看到示例代码为:


///
// Copyright (c) 2021, Tom Zhao personal. ("UsingSTLEx")
// This software is a personal tools project by Tom Zhao.
// Description:
///

#include 
#include 

using namespace std;

void printVector(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}

// operator=
void TzVectorCapacityCase01()
{
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	printVector(v1);
	if (v1.empty())
	{
		cout << "v1 is null" << endl;
	}
	else
	{
		cout << "v1 is not null" << endl;
		cout << "v1's capacity = " << v1.capacity() << endl;
		cout << "v1's size = " << v1.size() << endl;
	}

	// Resize re specifies the size. If the specified size is larger,
	// the new location is filled with 0 by default. You can replace the default filling with the overloaded version
	v1.resize(15,10);
	printVector(v1);

	// Resize re specifies the size. If the specified size is smaller, the excess elements will be deleted
	v1.resize(5);
	printVector(v1);
}

// other use ways.
void TzVectorCapacityCase02()
{
	// using empty()
	// empty() returns true if the vector is empty, otherwise false.
    std::cout << std::boolalpha;
    std::vector<int> numbers;
    std::cout << "Initially, numbers.empty(): " << numbers.empty() << '\n';
 
    numbers.push_back(42);
    std::cout << "After adding elements, numbers.empty(): " << numbers.empty() << '\n';

	// using size()
	// size() returns the number of elements in the vector.
	// size() is a member function of the vector class.
	// size() is a non-const member function.
	std::vector<int> nums {1, 3, 5, 7};
    std::cout << "nums contains " << nums.size() << " elements.\n";

	// using max_size()
	// The max_size() function returns the maximum number of elements that can be stored in the vector.
	std::vector<char> s;
    std::cout << "Maximum size of a 'vector' is " << s.max_size() << "\n";

	// using capacity()
	// capacity() returns the number of elements that the container has currently allocated space for.
	// capacity() does not change the size of the container.
	int sz = 200;
    std::vector<int> v1;
 
    auto cap = v1.capacity();
    std::cout << "initial capacity=" << cap << '\n';
 
    for (int n = 0; n < sz; ++n)
	{
        v1.push_back(n);
        if (cap != v1.capacity())
		{
            cap = v1.capacity();
            std::cout << "new capacity=" << cap << '\n';
        }
    }
 
    std::cout << "final size=" << v1.size() << '\n';
    std::cout << "final capacity=" << v1.capacity() << '\n';
	
	// using shrink_to_fit()
	// shrink_to_fit() is a member function of vector class.
	// shrink_to_fit() is used to reduce the capacity of the vector to the actual size of the vector.
	// shrink_to_fit() is useful when you know that the vector will not be resized in the future.
	std::vector<int> v;
    std::cout << "Default-constructed capacity is " << v.capacity() << '\n';
    v.resize(100);
    std::cout << "Capacity of a 100-element vector is " << v.capacity() << '\n';
    v.resize(50);
    std::cout << "Capacity after resize(50) is " << v.capacity() << '\n';
    v.shrink_to_fit();
    std::cout << "Capacity after shrink_to_fit() is " << v.capacity() << '\n';
    v.clear();
    std::cout << "Capacity after clear() is " << v.capacity() << '\n';
    v.shrink_to_fit();
    std::cout << "Capacity after shrink_to_fit() is " << v.capacity() << '\n';
    for (int i = 1000; i < 1300; ++i)
        v.push_back(i);
    std::cout << "Capacity after adding 300 elements is " << v.capacity() << '\n';
    v.shrink_to_fit();
    std::cout << "Capacity after shrink_to_fit() is " << v.capacity() << '\n';

	// using resize()
	// resize() is a member function of vector class.
	// resize() is used to change the size of the vector.
	// resize() is useful when you know that the vector will not be resized in the future.
	std::vector<int> c = {1, 2, 3};
    std::cout << "The vector holds: ";
    for(auto& el: c) std::cout << el << ' ';
    std::cout << '\n';
    c.resize(5);
    std::cout << "After resize up to 5: ";
    for(auto& el: c) std::cout << el << ' ';
    std::cout << '\n';
    c.resize(2);
    std::cout << "After resize down to 2: ";
    for(auto& el: c) std::cout << el << ' ';
    std::cout << '\n';
}

int main()
{
	TzVectorCapacityCase01();
	TzVectorCapacityCase02();

	system("pause");
	return 0;
}

     对于容量函数的使用技巧来讲,可以概括为:

  1. 判断是否为空 — empty
  2. 返回元素个数 — size
  3. 返回容器容量 — capacity
  4. 重新指定大小 — resize

5. vector插入与删除

     目前vector的插入与删除的操作,是能够支持对应的项放在需要的位置上,并把不需要的项从对应的位置上剔除的一种能力,具体可能会用到的函数原型有:

  • push_back(ele); //尾部插入元素ele
  • pop_back(); //删除最后一个元素
  • insert(const_iterator pos, ele); //迭代器指向位置pos插入元素ele
  • insert(const_iterator pos, int count,ele);//迭代器指向位置pos插入count个元素ele
  • erase(const_iterator pos); //删除迭代器指向的元素
  • erase(const_iterator start, const_iterator end);//删除迭代器从start到end之间的元素
  • clear(); //删除容器中所有元素

     项目对应的CMakeLists如下:

#[================================================================[.rst:
    Copyright (c)2021, Tom Zhao personal. ("UsingSTLEx")
    This software is a personal tools project by Tom Zhao.
    Description:
#]================================================================]

set(TZ_MAIN_NAME VectorInsertAndDelete)

set(TZ_MAIN_INCLUDE

)

set(TZ_MAIN_INC

)

set(TZ_MAIN_SRC
	main.cpp
)

add_executable(${TZ_MAIN_NAME}
	${TZ_MAIN_INCLUDE}
	${TZ_MAIN_INC}
	${TZ_MAIN_SRC}
)

set_property(TARGET ${TZ_MAIN_NAME} PROPERTY FOLDER "UsingVector")

     目前项目对应的是VectorInsertAndDelete, 具体的代码如下:


///
// Copyright (c) 2021, Tom Zhao personal. ("UsingSTLEx")
// This software is a personal tools project by Tom Zhao.
// Description:
///

#include 
#include 
#include 
#include 

using namespace std;

// print the vector for show.
void printVector(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}

void print_container(const std::vector<int>& c) 
{
    for (auto &i : c) {
        std::cout << i << " ";
    }
    std::cout << '\n';
}

void TzVectorInsertAndDeleteCase01()
{
	vector<int> v1;

	// insert at the end.
	v1.push_back(10);
	v1.push_back(20);
	v1.push_back(30);
	v1.push_back(40);
	v1.push_back(50);
	printVector(v1);

	// delete at the end.
	v1.pop_back();
	printVector(v1);
	// insert at the begin.
	v1.insert(v1.begin(), 100);
	printVector(v1);

	v1.insert(v1.begin(), 2, 1000);
	printVector(v1);

	// delete at the begin.
	v1.erase(v1.begin());
	printVector(v1);

	// clear the vector.
	v1.erase(v1.begin(), v1.end());
	v1.clear();
	printVector(v1);
}

void TzVectorInsertAndDeleteCase02() 
{
	std::vector<int> vec(3,100);
    printVector(vec);
 
    auto it = vec.begin();
    it = vec.insert(it, 200);
    printVector(vec);
 
    vec.insert(it,2,300);
    printVector(vec);
 
    // "it" no longer valid, get a new one:
    it = vec.begin();
 
    std::vector<int> vec2(2,400);
    vec.insert(it+2, vec2.begin(), vec2.end());
    printVector(vec);
 
    int arr[] = { 501,502,503 };
    vec.insert(vec.begin(), arr, arr+3);
    printVector(vec);
}

void TzVectorInsertAndDeleteCase03()
{
	std::vector<int> c {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    print_container(c);
 
    c.erase(c.begin());
    print_container(c);
 
    c.erase(c.begin() + 2, c.begin() + 5);
    print_container(c);
 
    // Erase all even numbers (C++11 and later)
    for (auto it = c.begin(); it != c.end(); )
	{
        if (*it % 2 == 0)
		{
            it = c.erase(it);
        }
		else
		{
            ++it;
        }
    }
    print_container(c);
}

void TzVectorInsertAndDeleteCase04()
{
	std::vector<std::string> letters;
 
    letters.push_back("abc");
    std::string s = "def";
    letters.push_back(std::move(s));
 
    std::cout << "vector holds: ";
    for (auto&& i : letters) std::cout << std::quoted(i) << ' ';
    std::cout << "\nMoved-from string holds " << std::quoted(s) << '\n';
}

void TzVectorInsertAndDeleteCase05()
{
	std::vector<int> container{1, 2, 3};
 
    auto print = [](const int& n) { std::cout << " " << n; };
 
    std::cout << "Before clear:";
    std::for_each(container.begin(), container.end(), print);
    std::cout << "\nSize=" << container.size() << '\n';
 
    std::cout << "Clear\n";
    container.clear();
 
    std::cout << "After clear:";
    std::for_each(container.begin(), container.end(), print);
    std::cout << "\nSize=" << container.size() << '\n';
}

void TzVectorInsertAndDeleteCase06()
{
	std::vector<int> numbers;
 
    print_container(numbers); 
 
    numbers.push_back(5);
    numbers.push_back(3);
    numbers.push_back(4);
 
    print_container(numbers); 
 
    numbers.pop_back();
 
    print_container(numbers); 
}

int main(int argc, char *argv[])
{
	TzVectorInsertAndDeleteCase01();
	TzVectorInsertAndDeleteCase02();
	TzVectorInsertAndDeleteCase03();
	TzVectorInsertAndDeleteCase04();
	TzVectorInsertAndDeleteCase05();
	TzVectorInsertAndDeleteCase06();

	system("pause");
	return 0;
}

     对于插入与删除函数的使用技巧来讲,可以概括为:

  1. 尾插 — push_back
  2. 尾删 — pop_back
  3. 插入 — insert (位置迭代器)
  4. 删除 — erase (位置迭代器)
  5. 清空 — clear

6. vector数据存取

     vector存取的形式主要是能够通过[]和at访问对应的下标来获取相关的数据,因此会用到的相关函数原型有:

  • at(int idx); //返回索引idx所指的数据
  • operator[]; //返回索引idx所指的数据
  • front(); //返回容器中第一个数据元素
  • back(); //返回容器中最后一个数据元素

     项目对应的CMakeLists如下:

#[================================================================[.rst:
    Copyright (c)2021, Tom Zhao personal. ("UsingSTLEx")
    This software is a personal tools project by Tom Zhao.
    Description:
#]================================================================]

set(TZ_MAIN_NAME VectorStoreData)

set(TZ_MAIN_INCLUDE

)

set(TZ_MAIN_INC

)

set(TZ_MAIN_SRC
	main.cpp
)

add_executable(${TZ_MAIN_NAME}
	${TZ_MAIN_INCLUDE}
	${TZ_MAIN_INC}
	${TZ_MAIN_SRC}
)

set_property(TARGET ${TZ_MAIN_NAME} PROPERTY FOLDER "UsingVector")

     项目对应的名字叫VectorStroreData, 具体的代码示例如下:


///
// Copyright (c) 2021, Tom Zhao personal. ("UsingSTLEx")
// This software is a personal tools project by Tom Zhao.
// Description:
///

#include 
#include 

using namespace std;

// print the vector for show.
void printVector(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void TzVectorStoreDataCase01()
{
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}

	// using [] to access the element.
	for (int i = 0; i < v1.size(); i++)
	{
		cout << v1[i] << " ";
	}
	cout << endl;

	// using at() to access the element.
	for (int i = 0; i < v1.size(); i++)
	{
		cout << v1.at(i) << " ";
	}
	cout << endl;

	cout << "the first element of v1 is: " << v1.front() << endl;
	cout << "the last element of v1 is: " << v1.back() << endl;
}

void TzVectorStoreDataCase02()
{
	std::vector<int> numbers {2, 4, 6, 8};
	// using [] to access the element.
    std::cout << "Second element: " << numbers[1] << '\n';
 
    numbers[0] = 5;
 
    std::cout << "All numbers:";
    for (auto i : numbers)
	{
        std::cout << ' ' << i;
    }
    std::cout << '\n';
}

// using at() to access the element.
void TzVectorStoreDataCase03()
{
	std::vector<int> data = { 1, 2, 4, 5, 5, 6 };
 
    // Set element 1
    data.at(1) = 88;
 
    // Read element 2
    std::cout << "Element at index 2 has value " << data.at(2) << '\n';
 
    std::cout << "data size = " << data.size() << '\n';
 
    try 
	{
        // Set element 6
        data.at(6) = 666;
    }
	catch (std::out_of_range const& exc)
	{
		// if the index is out of range, it will throw an exception.
        std::cout << exc.what() << '\n';
    }
 
    // Print final values
    std::cout << "data:";
    for (int elem : data)
        std::cout << " " << elem;
    std::cout << '\n';
}

int main(int argc, char *argv[])
{
	TzVectorStoreDataCase01();
	TzVectorStoreDataCase02();
	TzVectorStoreDataCase03();

	system("pause");
	return 0;
}

     对于数据存取函数的使用技巧来讲,可以概括为:

  1. 除了用迭代器获取vector容器中元素,[ ]at也可以。
  2. front返回容器第一个元素。
  3. back返回容器最后一个元素。

7. vector的交换(Swap)

     vector的交换能力,能够将不同的vector容器之间的元素进行交换,具体可能会用到的函数原型有:

     具体项目的CMakeLists如下:

#[================================================================[.rst:
    Copyright (c)2021, Tom Zhao personal. ("UsingSTLEx")
    This software is a personal tools project by Tom Zhao.
    Description:
#]================================================================]

set(TZ_MAIN_NAME VectorSwap)

set(TZ_MAIN_INCLUDE

)

set(TZ_MAIN_INC

)

set(TZ_MAIN_SRC
	main.cpp
)

add_executable(${TZ_MAIN_NAME}
	${TZ_MAIN_INCLUDE}
	${TZ_MAIN_INC}
	${TZ_MAIN_SRC}
)

set_property(TARGET ${TZ_MAIN_NAME} PROPERTY FOLDER "UsingVector")

     代码对应的名字叫VectorSwap, 具体的代码示例如下:


///
// Copyright (c) 2021, Tom Zhao personal. ("UsingSTLEx")
// This software is a personal tools project by Tom Zhao.
// Description:
///

#include 
#include 

using namespace std;

template<class Os, class Co> Os& operator<<(Os& os, const Co& co) {
    os << "{";
    for (auto const& i : co) { os << ' ' << i; }
    return os << " } ";
}

// print the vector for show.
void printVector(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void TzVectorSwapCase01()
{
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	printVector(v1);

	vector<int> v2;
	for (int i = 10; i > 0; i--)
	{
		v2.push_back(i);
	}
	printVector(v2);

	// swap v1 and v2.
	cout << "after swap:" << endl;
	v1.swap(v2);
	printVector(v1);
	printVector(v2);
}

void TzVectorSwapCase02()
{
	std::vector<int> a1{1, 2, 3}, a2{4, 5};
 
    auto it1 = std::next(a1.begin());
    auto it2 = std::next(a2.begin());
 
    int& ref1 = a1.front();
    int& ref2 = a2.front();
 
    std::cout << a1 << a2 << *it1 << ' ' << *it2 << ' ' << ref1 << ' ' << ref2 << '\n';
    a1.swap(a2);
    std::cout << a1 << a2 << *it1 << ' ' << *it2 << ' ' << ref1 << ' ' << ref2 << '\n';
 
    // Note that after swap the iterators and references stay associated with their
    // original elements, e.g. it1 that pointed to an element in 'a1' with value 2
    // still points to the same element, though this element was moved into 'a2'.
}

void TzVectorSwapCase03()
{
	vector<int> v;
	for (int i = 0; i < 100000; i++)
	{
		v.push_back(i);
	}

	cout << "the capacity of the v is: " << v.capacity() << endl;
	cout << "the size of the v is :" << v.size() << endl;

	v.resize(3);

	cout << "the capacity of the v is:" << v.capacity() << endl;
	cout << "the size of the v is :" << v.size() << endl;

	// Shrink memory
	vector<int>(v).swap(v); // Anonymous object

	cout << "the capacity of the v is: " << v.capacity() << endl;
	cout << "the size of the v is :" << v.size() << endl;
}

int main(int argc, char *argv[])
{
	TzVectorSwapCase01();
	TzVectorSwapCase02();
	TzVectorSwapCase03();

	system("pause");
	return 0;
}

     对于数据存取交换的使用技巧来讲,可以概括为: swap可以使两个容器互换,可以达到实用的收缩内存效果。

8. vector预先开辟容量(Reverse)

     对于预先开辟容量,是可以先为容器开辟一段地址,不赋值是不能够使用的,其目的是减少vector在动态扩展容量时的扩展次数,这样可以减少一定的开销。可能用到的函数原型如下:

  • reserve(int len);//容器预留len个元素长度,预留位置不初始化,元素不可访问。

     具体项目对应的CMakeLists如下:

#[================================================================[.rst:
    Copyright (c)2021, Tom Zhao personal. ("UsingSTLEx")
    This software is a personal tools project by Tom Zhao.
    Description:
#]================================================================]

set(TZ_MAIN_NAME VectorReverse)

set(TZ_MAIN_INCLUDE

)

set(TZ_MAIN_INC

)

set(TZ_MAIN_SRC
	main.cpp
)

add_executable(${TZ_MAIN_NAME}
	${TZ_MAIN_INCLUDE}
	${TZ_MAIN_INC}
	${TZ_MAIN_SRC}
)

set_property(TARGET ${TZ_MAIN_NAME} PROPERTY FOLDER "UsingVector")

     代码对应的项目是VectorReverse, 具体的代码示例如下:


///
// Copyright (c) 2021, Tom Zhao personal. ("UsingSTLEx")
// This software is a personal tools project by Tom Zhao.
// Description:
///

#include 
#include 
#include 
#include 

using namespace std;

constexpr int kMaxSize = 100000;

// minimal C++11 allocator with debug output
template <class Tp>
struct NAlloc {
    typedef Tp value_type;
    NAlloc() = default;
    template <class T> NAlloc(const NAlloc<T>&) {}
 
    Tp* allocate(std::size_t n)
    {
        n *= sizeof(Tp);
        std::cout << "allocating " << n << " bytes\n";
        return static_cast<Tp*>(::operator new(n));
    }
 
    void deallocate(Tp* p, std::size_t n) 
    {
        std::cout << "deallocating " << n*sizeof*p << " bytes\n";
        ::operator delete(p);
    }
};

template <class T, class U>
bool operator==(const NAlloc<T>&, const NAlloc<U>&) { return true; }
template <class T, class U>
bool operator!=(const NAlloc<T>&, const NAlloc<U>&) { return false; }

void TzVectorReverseCase01()
{
	vector<int> v;

	// Reserved space
	v.reserve(kMaxSize);

	int num = 0;
	int* p = NULL;
	for (int i = 0; i < kMaxSize; i++)
	{
		v.push_back(i);
		if (p != &v[0])
		{
			p = &v[0];
			num++;
		}
	}

	cout << "num:" << num << endl;
}

void TzVectorReverseCase02()
{
	int sz = 100;
    std::cout << "using reserve: \n";
    {
        std::vector<int, NAlloc<int>> v1;
        v1.reserve(sz);
        for(int n = 0; n < sz; ++n)
            v1.push_back(n);
    }
    std::cout << "not using reserve: \n";
    {
        std::vector<int, NAlloc<int>> v1;
        for(int n = 0; n < sz; ++n)
            v1.push_back(n);
    }
}

int main(int argc, char *argv[])
{
	TzVectorReverseCase01();

	system("pause");
	return 0;
}

     对于数据存取交换的使用技巧来讲,可以概括为: 如果数据量较大,可以一开始利用reserve预留空间。

个人格言

用心去感受你自己需要坚持的生活,未来慢慢会给你答案的。

你可能感兴趣的:(STL,项目,C++,c++,cmake,c,经验分享,vscode)