龙空技术网

c++ 疑难杂症(4) std:vector

我要上班 514

前言:

现在看官们对“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打乱算法