前言:
现在看官们对“c把vector打乱算法”大概比较关注,我们都需要学习一些“c把vector打乱算法”的相关知识。那么小编也在网摘上汇集了一些有关“c把vector打乱算法””的相关知识,希望我们能喜欢,小伙伴们快快来了解一下吧!std::vector的使用频率比较高, 有必要盘盘它。
0.概念
std::vector 是 C++ 标准库中的一个动态数组模板类。它允许您存储和操作一系列连续的元素。以下是关于 std::vector 的几个关键点:
动态大小:与常规数组不同,std::vector 的大小可以在运行时改变。您可以使用 push_back(), pop_back(), insert(), erase(), 和其他成员函数来更改向量的大小。连续存储:std::vector 保证其元素在内存中是连续存储的,这使得访问和修改元素非常快速。容量增长:当您向 std::vector 添加元素时,它会自动重新分配内存以容纳更多的元素,通常会按比例增长其容量。迭代器:std::vector 提供了随机访问迭代器,这使得它可以像常规数组一样进行索引,但同时也支持许多 STL(标准模板库)算法。内存管理:std::vector 负责自己的内存管理,它会自动调整其大小以适应元素的需要,并在必要时重新分配内存。类型安全:由于 std::vector 是模板类,因此它可以存储任何类型的元素,并且类型安全。效率:虽然 std::vector 需要维护内部指针和数据结构,但大多数操作(如添加或删除元素)的开销都相对较低。对于许多应用,使用 std::vector 比使用常规数组或手动管理内存更高效。1.示例
代替字符数组
#include<iostream>#include <vector>#include <memory>void main() { //模拟代替字符数组 char buf[4096]; std::vector<char> buf(4096); strcpy(buf.data(), "hello world"); std::cout << strlen(buf.data()) << std::endl; std::cout << buf.data() << std::endl; //当然现在智能指针使用替换 //std::unique_ptr<char[]> ptr(new char[4096]);}
常规操作
#include<iostream>#include <vector>#include <algorithm> int main() { std::vector<std::string> vecS({"one", "two"}); //添加 vecS.push_back("three"); vecS.emplace_back("four"); vecS.insert(vecS.begin(), "zero"); vecS.insert(vecS.end(), { "five", "six" }); vecS.emplace(vecS.end(), "seven"); vecS.clear();//全部删除 vecS.assign(7, "ok");//分配7个串, 每个都是"ok" vecS.assign({"zero", "one", "two", "three", "four", "five", "size", "seven"}); //访问 if (0 == vecS[2].compare("two")) { std::cout << vecS[2] << std::endl; //打印输出: two } //遍历 for (auto elem : vecS) { //for (std::string elem : vecS) { std::cout << elem << " "; } std::cout << std::endl; //打印输出: zero one two three four five six seven for (auto& elem : vecS) { //for (std::string& elem : vecS) { //for (const auto& elem : vecS) { //for (const std::string& elem : vecS) { std::cout << elem << " "; } std::cout << std::endl; //打印输出: zero one two three four five six seven std::for_each(vecS.begin(), vecS.end(), [](std::string& elem) { std::cout << elem << " "; }); std::cout << std::endl; //打印输出: zero one two three four five six seven //查找 std::vector<std::string>::iterator it; it = std::find(vecS.begin(), vecS.end(), "three"); it = std::find_if(vecS.begin(), vecS.end(), [](std::string& elem) { return 0 == elem.compare("three"); }); //排序 (先打乱, 然后再0-7排序) std::sort(vecS.begin(), vecS.end());//默认的,打乱了0-7排序 std::sort(vecS.begin(), vecS.end(), [](const std::string& x, const std::string& y) { //只是演示,不考虑效率 int x1 = 0, y1 = 0; std::string cmp[] = { "zero", "one", "two", "three", "four", "five", "size", "seven" }; for (int i = 0; i < sizeof(cmp) / sizeof(cmp[0]); i++) { if (x1 == 0 && 0 == cmp[i].compare(x)) { x1 = i; } if (y1 == 0 && 0 == cmp[i].compare(y)) { y1 = i; } } return x1 < y1; }); //删除 vecS.pop_back();//删除最后一个"five" vecS.erase(vecS.begin());//删除首个"zero" vecS.erase(std::find(vecS.begin(), vecS.end(), "three")); //遍历删除 for (auto iter = vecS.begin(); iter != vecS.end(); ++iter) { if (0 == iter->compare("four")) { vecS.erase(iter--);//注意,删除时倒退 continue; } std::cout << *iter <<" "; } std::cout << std::endl; //打印输出: one two five six //复制 std::vector<std::string> vecCopy(vecS); vecCopy.clear(); vecCopy.insert(vecCopy.begin(), vecS.begin(), vecS.end()); vecCopy.clear(); vecCopy = vecS; //vecCopy.operator=(vecS); vecCopy.clear(); vecCopy.assign(vecS.begin(), vecS.end()); if (vecCopy == vecS) { std::cout << "same" << std::endl; } return 0;}/*打印输出:twoone two three four five size sevenone two three four five size sevenone two three four five size seventwo five sizesame*/
移动语义支持
#include<iostream>#include <vector>#include <algorithm> int main() { class A { int x = 0; public: A(int _x) : x(_x) { std::cout << "A() : x=" << x << std::endl; } A(const A& a) {//拷贝构造函数 x = a.x; std::cout << "A(const A& a) : x=" << x << std::endl; } A(A&& a) noexcept { //移动构造函数 x = a.x; a.x = 0; std::cout << "A(A&& a) : x=" << x << std::endl; } ~A() { std::cout << "~A() : x=" << x << std::endl; } A& operator=(const A& a) { //拷贝赋值运算符 if (this != &a) { x = a.x; } std::cout << "operator=(const A& a) : x=" << x << std::endl; return *this; } A& operator=(A&& a) noexcept { //移动赋值运算符 if (this != &a) { x = a.x; a.x = 0; } std::cout << "operator=(const A& a) : x=" << x << std::endl; return *this; } void show() { std::cout << "x=" << x << std::endl; } }; std::vector<A> vec; //添加成员方法基本上都添加了移动语义支持 //void push_back(_Ty&& _Val) //iterator insert(const_iterator _Where, _Ty&& _Val) //decltype(auto) emplace_back(_Valty&&... _Val) //iterator emplace(const_iterator _Where, _Valty&&... _Val) //下面举例说明: {//移动语义 A a(1); vec.push_back(std::move(a)); vec.push_back(A(2)); //void push_back(_Ty&& _Val) } {//移动语义 vec.emplace_back(A(3)); vec.emplace_back(4); //decltype(auto) emplace_back(_Valty&&... _Val) } {//移动语义 A a(5); vec.insert(vec.end(), std::move(a)); vec.insert(vec.end(), A(6)); //iterator insert(const_iterator _Where, _Ty&& _Val) } { A a(7); vec.emplace(vec.end(), a); vec.emplace(vec.end(), 8); //iterator emplace(const_iterator _Where, _Valty&&... _Val) } {//通过移动转移 vec[vec.size() - 1].show(); //打印: 8 A a = std::move(vec[vec.size() - 1]); vec[vec.size() - 1].show();//打印: 0 vec.pop_back();//转移之后,无效了,应该移除 } {//通过移动转移 std::vector<A> vec1(std::move(vec)); std::vector<A> vec2 = std::move(vec1); vec = std::move(vec2); } {//通过移动转移 //auto func = [](std::vector<A>&& a)->std::vector<A>&& { return std::forward<std::vector<A>>(a); }; auto func = [](std::vector<A>&& a) { return std::forward<std::vector<A>>(a); }; auto vec1 = func(std::forward<std::vector<A>>(vec)); vec = std::move(vec1); } return 0;}
解析: 这段C++代码定义了一个名为A的类,该类有一个私有成员变量x,以及一些公共成员函数,如构造函数、拷贝构造函数、移动构造函数、析构函数、拷贝赋值运算符和移动赋值运算符。 演示std::vector的成员方法中关于移动语义的支持。移动语义是一种优化技术,它可以减少对象拷贝的开销,提高程序的性能。在C++11中引入了右值引用,使得移动语义成为可能。
首先,代码定义了一个名为A的类,该类有一个成员方法show(),用于打印对象的值。
然后,代码创建了一个std::vector<A>类型的变量vec,并使用push_back()方法向其中添加了几个A类型的对象。
接下来,代码演示了四种不同的方法来向vec中添加元素:
使用push_back()方法,并将参数作为右值传递。这种方法会自动调用A类的移动构造函数,从而实现移动语义。
使用emplace_back()方法,并将参数作为右值传递。这种方法会自动调用A类的移动构造函数,从而实现移动语义。
使用insert()方法,并将参数作为右值传递。这种方法会自动调用A类的移动构造函数,从而实现移动语义。
使用emplace()方法,并将参数作为右值传递。这种方法会自动调用A类的移动构造函数,从而实现移动语义。
最后,代码演示了如何通过移动语义将对象从一个vector转移到另一个vector中。
注意:在实际编程中,为了更好地利用移动语义,可以尽量使用右值引用作为函数参数,并在需要时使用std::forward()进行类型转换。
与智能指针结合
#include<iostream>#include <vector>#include <memory>int main() { class A { int x = 0; public: A(int _x) : x(_x) { std::cout << "A() : x=" << x << std::endl; } void show() { std::cout << "x=" << x << std::endl; } }; {//vector 存放 shared_ptr auto func = [](A* a) { std::cout << "delete" << std::endl; delete a; }; std::vector<std::shared_ptr<A>> vec; vec.push_back(std::shared_ptr<A>(new A(1), func)); vec.push_back(std::make_shared<A>(2)); vec.emplace(vec.end(), new A(3)); vec.emplace_back(new A(4)); vec.insert(vec.end(), { std::make_shared<A>(5), std::shared_ptr<A>(new A(6), func) }); while (!vec.empty()) { vec.pop_back(); } } {//shared_ptr 包裹 std::vector auto func = [](std::vector<A>* ptr) { std::cout << "delete vector" << std::endl; ptr->clear(); delete ptr; }; std::shared_ptr<std::vector<A>> ptr = std::shared_ptr<std::vector<A>>(new std::vector<A>(), func); ptr.reset(); } return 0;}/*第一个代码块:在这个代码块中,我们创建一个 std::vector<std::shared_ptr<A>> 并向其中添加元素。定义一个 lambda 函数 func,它接受一个指向 A 的指针,并删除它。创建向量 vec,用于存放 std::shared_ptr<A>。使用不同的方法向 vec 中添加元素:使用 std::shared_ptr<A>(new A(1), func) 创建一个智能指针,并使用自定义删除器。使用 std::make_shared<A>(2) 创建一个智能指针。使用 vec.emplace(vec.end(), new A(3)) 在向量的末尾直接构造一个对象。使用 vec.emplace_back(new A(4)) 在向量的末尾直接构造一个对象。使用 vec.insert(vec.end(), { std::make_shared<A>(5),std::shared_ptr<A>(new A(6), func) }) 在向量的末尾插入两个元素。通过循环删除向量的所有元素,以展示自定义删除器的使用。第二个代码块:在这个代码块中,我们使用 std::shared_ptr 来管理一个包含 A 对象的 std::vector。定义另一个 lambda 函数 func,它接受一个指向 std::vector<A> 的指针,并清空向量并删除它。创建 std::shared_ptr<std::vector<A>> ptr,并使用 lambda 函数作为删除器。然后重置 ptr 以触发删除器。*/
c++ 疑难杂症(1) std::thread
c++ 疑难杂症(2) std::move
c++ 疑难杂症(3) 模板特化
c++ 疑难杂症(5) std::pair
c++ 疑难杂症(6) std::map
c++ 疑难杂症(7) std::tuple
c++ 疑难杂症(8) std::multimap
标签: #c把vector打乱算法