精华内容
下载资源
问答
  • vectorpush_back操作是将一个元素插入vector的末尾。源码如下:template void YVector::push_back(const T&x){if (finish !=end_of_storage){construct(finish, x);++finish;}else{insert_aux(finish, x);}}...

    vector的push_back操作是将一个元素插入vector的末尾。

    源码如下:

    template

    void YVector::push_back(const T&x)

    {if (finish !=end_of_storage)

    {

    construct(finish, x);++finish;

    }else{

    insert_aux(finish, x);

    }

    }

    函数insert_aux

    template

    void YVector::insert_aux(iterator position, const T&x)

    {if (finish !=end_of_storage)

    {

    construct(finish,*(finish - 1));++finish;

    T copy_x=x;

    copy_backward(position, finish- 2, finish - 1);*position =copy_x;

    }else{const size_type old_size =size();const size_type new_size = old_size == 0 ? 1 : 2 *old_size;

    iterator new_start=data_allocator::allocate(new_size);

    iterator new_finish=new_start;try{

    new_finish=uninitialized_copy(start, position, new_start);

    construct(new_finish, x);++new_finish;

    new_finish=uninitialized_copy(position, finish, new_finish);

    }catch(...)

    {

    destroy(new_start, new_finish);

    data_allocator::deallocate(new_start, new_size);throw;

    }

    destroy(begin(), end());

    deallocate();

    start=new_start;

    finish=new_finish;

    end_of_storage= new_start +new_size;

    }

    }

    需要理解以上源码并不容易。看我一一道来。

    1.start,finish,end_of_storage

    首先必须了解vector的数据结构。如图:

    d84488485eaeeab62ab43020cc2e5d79.png

    vector是一段连续的内存空间。start,finish,end_of_storage三个指针描述了空间状态,这三个是普通的指针。start到finish是已经使用的内存,里面有元素。finish到end_of_storage是未使用的内存,里面没有元素。

    由此三个指针可以得出一些简单的操作。

    iterator begin() { return start; } //起始位置

    iterator end() { return finish; } //结束位置

    size_type size() const { return size_type(end() - begin()); } //已可用大小

    size_type capacity() const { return size_type(end_of_storage - begin()); } //申请的内存大小

    bool empty() { return begin() == end(); } //是否为空

    reference operator[](size_type n) { return *(begin() + n); } //[]操作

    reference front() { return *begin(); } //首元素

    reference back() { return *(end() - 1); } //尾元素

    其中一些定义

    typedef T value_type;

    typedef value_type*pointer;

    typedef value_type*iterator;

    typedef value_type&reference;

    typedef size_t size_type;

    2.construct,destroy

    这个两个是全局的构造和析构函数。其中construct是调用placement new。

    有关于placement new,参考 http://www.cnblogs.com/luxiaoxun/archive/2012/08/10/2631812.html

    templateinlinevoid construct(T1* p, const T2&value)

    {new(p)T1(value);

    }

    placement new可以简单理解成在已经分配好的空间上构造。

    在puch_back这里的情境中,如果内存的备用区还有空间,则用x在finish指向的空间上构造,同时移动finish指针。这里原本finish指向的空间是已经申请了的,所以使用placement new。

    if (finish !=end_of_storage)

    {

    construct(finish, x);++finish;

    }

    destroy有两个版本。destroy实现较复杂,参看《STL源码剖析》第二章。只需知道destroy会在指定范围进行析构。

    template inlinevoid destroy(T*pointer)

    {

    pointer->~T();

    }

    templateinlinevoiddestroy(ForwardIterator first, ForwardIterator last)

    {

    //实现略

    }

    3.allocate,deallocate

    注意到定义类时出现了Alloc,这其实是配置器。vector默认使用alloc配置器。

    template

    在基本的alloc上封装一层simple_alloc。如下:

    template

    classsimple_alloc {static T* allocate(size_t n)

    { return n == 0 ? 0 : (T*)Alloc::allocate(n * sizeof(T)); }static T* allocate()

    { return (T*)Alloc::allocate(sizeof(T)); }static void deallocate(T *p, size_t n)

    { if (n == 0) Alloc::deallocate(p, n * sizeof(T)); }static void deallocate(T *p)

    { Alloc::deallocate(p, sizeof(T)); }

    };

    实际上内部实现就是调用malloc和free,但是会有复杂的分级配置处理。在此不再讨论。参看《STL源码剖析》第二章。

    可以就简单的把allocate,deallocate理解成malloc,free来辅助记忆,但务必记得没那么简单。

    4.uninitialized_copy,copy_backward

    uninitialized_copy处理如下图:

    69408527c3d9ccc930b59ffa4b02f132.png

    看起来好复杂……来看一下原型:

    template inline ForwardIterator

    uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result)

    {return__uninitialized_copy(first, last, result, value_type(result));

    }

    如果[result,result + (last - first))范围内的迭代器都指向未初始化区域,则uninitialized_copy()会使用copy construct给输入来源[first,last)范围内的每一个对象产生一个拷贝放进输出范围。

    更深的实现也贴出来:

    template inline ForwardIterator

    __uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result, T*)

    {

    typedef typename __type_traist::is_POD_type is_POD_type is_POD;return__uninitialized_copy_aux(first, last, result, is_POD());

    }

    templateinline ForwardIterator

    __uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result, __true_type)

    {returncopy(first, last, result);

    }

    templateinline ForwardIterator

    __uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result, __false_type)

    {

    ForwardIterator cur=result;for (; last != first; first++, cur++)

    {

    construct(&*cur, *first);

    }returncur;

    }

    这里面的逻辑是,首先把result的value_type得出,判断是否是POD类型……

    如果是POD类型,则调用copy函数,如果不是POD类型,则一个一个调用construct()

    所谓POD类型,指的是拥有无意义的构造、析构、拷贝、赋值函数的类型…能不能理解成比较简单的类。

    像是如果类成员里有一个其他类的指针,这种复杂的类,需要有特殊的构造函数,就没有默认的那个构造函数。因此是non-POD类型。

    接下来回到push_back。insert_aux里面判断还有备用空间的地方,有一个copy_backword函数。来看一下实现:

    templateBidirectionalIterator2 copy_backward ( BidirectionalIterator1 first,

    BidirectionalIterator1 last,

    BidirectionalIterator2 result )

    {while (last!=first) *(--result) = *(--last);returnresult;

    }

    作用是将一个范围中的元素按逆序拷贝到新的位置处。insert_aux截取如下:

    if (finish !=end_of_storage)

    {

    construct(finish,*(finish - 1));++finish;

    T copy_x=x;

    copy_backward(position, finish- 2, finish - 1);*position =copy_x;

    }

    这里面有两个问题。第一为什么要有一份拷贝T copy_x = x;问题的答案参考知乎 https://www.zhihu.com/question/56911557/answer/150928396

    第二个 copy_backward(position,finish - 2,finish - 1) 在插入位置是末尾的时候不会死循环吗?黑人问号?

    position其实是finish - 1,也就是说传入参数后first比last还后面,那岂不是死循环?

    引用:

    1.《STL源码剖析》

    2.http://www.cnblogs.com/luxiaoxun/archive/2012/08/10/2631812.html

    展开全文
  • 1.已知vector中的push_back函數是把數字或者其他類型往最後放,但是為什麼這個代碼會出現我不想要的訊息?新手求大神指點 m(._.)m 感恩輸入西元年,結果依照閏年有所不同傳遞一個1~12月的天數vector days;int years;...

    1.已知vector中的push_back函數是把數字或者其他類型往最後放,但是為什麼這個代碼會出現我不想要的訊息?新手求大神指點 m(._.)m 感恩

    輸入西元年,結果依照閏年有所不同

    傳遞一個1~12月的天數

    vector days;

    int years;

    cout << "Please give me your years:"<

    while (cin >> years) {

    if (years == 0)

    break;

    }

    if (years % 4 == 0 && years % 100 != 0) {

    for (int i = 1; i != 13; i++) {

    if (i == 1 || 3 || 5 || 7 || 8 || 11) {

    days.push_back(31);

    }

    if (i == 2) { days.push_back(29); }

    else{ days.push_back(30); }

    }

    }

    else {

    for (int i = 1; i != 13; i++) {

    if (i == 1 || 3 || 5 || 7 || 8 || 11) {

    days.push_back(31);

    }

    if (i == 2) { days.push_back(28); }

    else { days.push_back(30); }

    }

    }

    for (auto r : days) { cout << r << " "; }

    return 0;

    7b05f9047879b5e6c362c55184de5f3e.png

    明明是12個月,我卻得到25個數字

    我希望第二個數字代表2月,但數字卻不是28或29天

    展开全文
  • vector如果不new是在栈上的,这是众人皆知的。如下面的代码:class Solution {public:vector> generate(int numRows) {vector> result;...result.push_back(temp);}for (int i=0; icout<}re...

    vector如果不new是在栈上的,这是众人皆知的。

    如下面的代码:

    class Solution {

    public:

    vector> generate(int numRows) {

    vector> result;

    for (int i=0; i

    vector temp(i+1,1);

    cout<

    result.push_back(temp);

    }

    for (int i=0; i

    cout<

    }

    return result;

    }

    };

    得到的结果如下:

    0x7fff5fbff5f0

    0x7fff5fbff5f0

    0x7fff5fbff5f0

    0x100105540

    0x100105558

    0x100105570

    Program ended with exit code: 0

    那么如果使用了new了呢?众所周知,使用new之后所得到的结果是在堆上的。

    但是我们来看下面的代码:

    class Solution {

    public:

    vector> generate(int numRows) {

    vector> result;

    for (int i=0; i

    vector *temp =new vector();

    cout<

    result.push_back(*temp);

    }

    for (int i=0; i

    cout<

    }

    return result;

    }

    };

    得到的结果如下:

    0x1001054a0

    0x1001054e0

    0x1001054c0

    0x100105560

    0x100105578

    0x100105590

    Program ended with exit code: 0

    依旧不相同,是为什么呢?

    因为vector的push_back()机理是这样的,

    它并不是一种深度拷贝,而是一种浅拷贝,

    即,将要push_back元素所对应的所有值拷贝到vector name所分配的那块空间去,

    而不是借用别人已经存在的那块地址。

    有点绕,我们来看一道Leetcode:leetcode 118 Pascal's Triangle

    ——————————————

    这是我原来的解法,是wrong answer,

    调试了一下,发现无论numRows是多少,result数组依然全部是1。

    class Solution {

    public:

    vector> generate(int numRows) {

    vector> result;

    for (int i=0; i

    vector temp(i+1,1);

    result.push_back(temp);

    for (int j=1; j

    temp[j]=result[i-1][j-1]+result[i-1][j];

    }

    }

    return result;

    }

    };

    原因就是上面说的,push_back到result的并不是temp本身,而是temp所对应的值们。

    所以对temp[j]造成的改动并不影响result找个vector。

    所以正解如下:

    class Solution {

    public:

    vector> generate(int numRows) {

    vector> result;

    for (int i=0; i

    vector temp(i+1,1);

    result.push_back(temp);

    for (int j=1; j

    result[i][j]=result[i-1][j-1]+result[i-1][j];

    }

    }

    return result;

    }

    };

    展开全文
  • vector().push_back(T(args));相当于vector().emplace_back(args);C++11之前,push_back先后调用了构造函数、拷贝构造函数(临时申请堆空间,影响性能);C++11之后,push_back先后调用了构造函数、转移构造函数。在...

    vector().push_back(T(args));

    相当于

    vector().emplace_back(args);

    C++11之前,push_back先后调用了构造函数、拷贝构造函数(临时申请堆空间,影响性能);

    C++11之后,push_back先后调用了构造函数、转移构造函数。

    在C++11的基础上,emplace_back比push_back少了一次转移构造函数,只有构造函数。

    在www.cplusplus.com的std::vector::push_back的注解中,提到参数可能被拷贝或移动(即 左值引用 或 右值引用):

    Adds a new element at the end of the vector, after its current last element. The content of val is copied (or moved) to the new element.

    大致代码如下:

    std::vector<:string> v;

    int count = 10000000;//分别for循环调用10000000次

    v.reserve(count); //预分配十万大小,排除掉分配内存的时间

    // 方式一:push_back(const string&),参数是左值引用(传统的引用)

    {

    // push_back string:327ms【最慢】

    std::string temp("ceshi"); // 一次std::string构造函数

    v.push_back(temp); // 左值引用,临时变量的构造函数,拷贝构造

    }

    // 方式二:push_back(string &&), 参数是右值引用

    {

    // push_back move(string):213ms

    std::string temp("ceshi"); // 一次std::string构造函数

    v.push_back(std::move(temp)); // 右值引用,临时变量的构造函数,拷贝构造

    // push_back(string):229 ms

    v.push_back(std::string("ceshi")); // 一次std::string构造函数,临时变量的构造函数,右值引用,拷贝构造

    // push_back(c string):215 ms

    v.push_back("ceshi"); // 比上面两种稍微快一点点,少了一次std::string构造函数

    }

    // 方式三:emplace_back(c string):122 ms【最块】

    {

    v.emplace_back("ceshi"); // 只有一次构造函数,不调用拷贝构造函数,速度最快

    }

    参考资料:

    展开全文
  • 无法将gl_ :: mat4元素push_back转换为头文件中声明的向量(Can't push_back a glm::mat4 element into a vector declared in a header file)我在头文件中有一个矢量delared ah :// in a.hclass A {public:...std::...
  • 此外,本文还将简述push对应的stack与queue系列,常见方法的介绍,以及与push_back相对应的vector系列常见方法介绍。详见下文。list 也是使用 push_back .【正文】push_back 方法介绍vector::v...
  • 要知道,向 vector 容器中添加元素的唯一...在 《STL vector容器详解》一节中,已经给大家列出了 vector 容器提供的所有成员函数,在这些成员函数中,可以用来给容器中添加元素的函数有 2 个,分别是 push_back() 和...
  • 转自:问题: 将N个元素使用push_back插入到vector中, 求push_back操作的复杂度。 参考:C++ std::vectorpush_back操作时间复杂度分析 分析如下: 考虑vector每次内存扩充两倍的情况: 如果我们插入N个元素,则...
  • vector::push_back()的输入参数是对象本身; vector::emplace_back()的输入参数是构造函数的参数,它可以根据这些参数自动构造一个对象。 #include <iostream> #include <vector> using namespace ...
  • c++ push_back与emplace_back

    2021-04-15 11:28:32
    push_back与emplace_back 本节直接讨论在向容器添加数据时,插入(push_back、push_front、insert等)和置入(emplace_back)的内存性能情况,深入了解C++的内部机制。考虑下面代码: vector<string> vs; vs.push_...
  • <div><p>该提问来源于开源项目:Bhupesh-V/30-seconds-of-cpp</p></div>
  • C++ Vector容器的push_back()与pop_back()函数push_back( )pop_back( )参考链接 push_back( ) 函数将一个新的元素加到vector的最后面,位置为当前最后一个元素的下一个元素 push_back() 在Vector最后添加一个...
  • emplace_back能就地通过参数构造对象,不需要拷贝或者移动内存,相比push_back能更好地避免内存的拷贝与移动,使容器插入元素的...vector push_back 源码实现: void push_back(const value_type &__x) { ...
  • C++ 中”emplace_back” 与 “push_back” 的区别 emplace_back和push_back都是向容器内添加数据. 对于在容器中添加类的对象时, 相比于push_back,emplace_back可以避免额外类的复制和移动操作. “emplace_back ...
  • push_back()函数向容器中加入一个临时对象(右值元素)时, 首先会调用构造函数生成这个对象,然后条用拷贝构造函数将这个对象放入容器中, 最后释放临时对象。但是emplace_back()函数向容器中中加入临时对象, 临时...
  • C++中push_back,push_front,insert的用法

    千次阅读 2018-09-15 15:37:34
    之前在介绍vector的初始化的时候有介绍到容器的push_back操作,push_back基本所有容器都支持,而push_front则是有的支持有的不支持。insert和push_back一样都支持...
  • vector中没有push_front和pop_front,只有push_back和pop_back。 vector是开辟一块空间来作为数组来存放元素(随机迭代器),如果有了pop_front,pop_back这个功能则很容易造成内存碎片,pop_front会造成头部内存产生...
  • 一直都说尽量用C++11的emplace_back替换push_back,前者的效率究竟比后者快多少不甚了解,写个demo简单测试下看看,下面这个demo程序我写了个Pt类用于测试,除了普通构造函数外还有拷贝构造和移动构造,3个静态变量...
  • #include #include #include using namespace std; int main() { vectorv1; //创建一个向量存储容器 double vectorv2; //创建一个向量存储容器 ...i++) // push_back(elem)在数组最后添加数据el
  • vector之慎用push_back

    2020-07-02 13:22:49
    vector之慎用push_back push_back是在vector有效元素的末尾添加新元素,所以首先要明白resize与reserve的区别 先上结论: vec.resize(size)后用push_back,是在vec[size]处开始添加元素,所以resize与push_back不要...
  • 网上最常讲的:C++ vector::push_back 会先创建临时对象,然后将临时对象拷贝到容器中,最后销毁临时对象;但是 emplace_back 仅会在容器中原地创建一个对象出来,减少临时对象拷贝、销毁的步骤,所以性能更高。我...
  • 之前在介绍vector的初始化的时候有介绍到容器的push_back操作,push_back基本所有容器都支持,而push_front则是有的支持有的不支持。insert和push_back一样,所有容器都支持。 这里简单介绍一下三种不同添加元素的...
  • stl vector 函数 C ++ vector :: push_back()函数 (C++ vector::push_back() function) vector::push_back() is a library function of "vector" header, it is used to insert/add an element at the end of the ...
  • stl vector push_back解析

    2020-02-22 13:50:53
    查看 Visual Studio 2013的stl vector代码,发现push_back要先判断元素是否本来就在vector里面,再分情况push_back. 粗看不解,以为多此一举,其实里面暗藏玄机。 所以就搜索一下,发现了这个问题“Is it safe to ...
  • vector中的push_back

    2017-11-12 20:51:42
    vector v; v.push_back(1); //v里面为: 1 v.push_back(2); //v里面为: 1,2 v.push_back(3); //v里面为: 1,2,3 vectorpush_back函数的意思是在vector的末尾插入一个元素。
  • c++ emplace_back与push_back

    2020-02-01 18:33:02
    容器的emplace_back与push_back方法 emplace_back针对添加的元素为 “某个对象struct、class” ,可以直接写参数,函数自动调用构造函数,而不用先创建对象再添加。 push_back需要先创建对象,再添加。 emplace、...
  • vector push_back和at

    2016-09-09 10:09:32
    1.vectorpush_back函数的意思是在vector的末尾插入一个元素。 2.vector简单理解为动态一维数组push_back作用是在这个一维数组尾部插入一个元素 vector v; v.push_back(1); //v里面是: 1 v.push_back(2); //v...
  • vector_push_back

    2019-05-08 00:37:05
    // vector::push_back #include <iostream> #include <vector> //在末尾添加元素 //在向量的最后一个元素之后,在其末尾添加一个新元素。val的内容被复制(或移动)到新元素。 //这有效地将容器...
  • push_back:先在调用处构造一次 class,传递进push_back内后再进行拷贝到缓冲区。 emplace_back:在内部直接将构造class的参数转发构造到缓冲区。 如果以上说法不好理解,那么用代码来表示。 // 该 Class 支持...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,365
精华内容 3,346
关键字:

push_backvector