精华内容
下载资源
问答
  • vector的push_back

    2014-11-18 14:51:04
    这两天在实际程序中使用 STL vector push_back 类对象时出现问题,偶尔发现 vectorpush_back调用类对象拷贝构造函数和析构函数有点特别,简单做下分析。 程序代码: cat > test.cpp ...

    建议: 使用vector进行push_back 对象的时候,应事先分配好对象的空间。不然向空的vector进行push_back的时候,会因为内存不够,导致vector重新申请内存,则会复制对象,

    在复制对象的过程中,会调用浅拷贝(默认复制构造)函数,导致对象中的 指针数据成员 指向的内存  泄露以及接下来的重复释放 [  add by  zhai ]

    这两天在实际程序中使用 STL 的 vector push_back 类对象时出现问题,偶尔发现 vector 在 push_back 时的调用类对象的拷贝构造函数和析构函数有点特别,简单做下分析。

    程序代码:

    cat > test.cpp
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    #include <iostream>
    #include <vector>
     
    using namespace std;
     
    struct sss
    {
    public:
        explicit sss(int val) : value(val)
        {
            cout << "---init sss " << this << ", value:" << value << endl;
        }
     
        sss(const sss& org)
        {
            cout << "---copy " << &org << " to " << this << endl;
            value = org.value;
        }
     
        ~sss()
        {
            cout << "---destory sss " << this << ", value:" << value << endl;
        }
      
        int value;
    };
     
    int main(int argc, char ** argv)
    {
        sss s_tmp(11);
        int i = 0;
        vector<sss> vvv;
     
        for (i = 0; i < 5; i++) {
            s_tmp.value++;
            vvv.push_back(s_tmp);
            cout << "size: " << vvv.size() << ", capacity: " << vvv.capacity() << endl;
        }
     
        return 0;
    }

    功能很简单,main 中定义一个 sss 类对象和对应的 vector,然后在循环中改类成员的值,并依次 push_back 到 vector 中,类的构造函数、析构函数、拷贝构造函数中都加了对应的打印输出。循环运行了5次,往 vector 中增加了5个类成员。

    实际运行输出如下:


    ---init sss 0x22ff20, value:11
    ---copy 0x22ff20 to 0x5d2a58
    size: 1, capacity: 1
    ---copy 0x5d2a58 to 0x5d2ad8
    ---copy 0x22ff20 to 0x5d2adc
    ---destory sss 0x5d2a58, value:12
    size: 2, capacity: 2
    ---copy 0x5d2ad8 to 0x5d2ae8
    ---copy 0x5d2adc to 0x5d2aec
    ---copy 0x22ff20 to 0x5d2af0
    ---destory sss 0x5d2ad8, value:12
    ---destory sss 0x5d2adc, value:13
    size: 3, capacity: 4
    ---copy 0x22ff20 to 0x5d2af4
    size: 4, capacity: 4
    ---copy 0x5d2ae8 to 0x5d2b00
    ---copy 0x5d2aec to 0x5d2b04
    ---copy 0x5d2af0 to 0x5d2b08
    ---copy 0x5d2af4 to 0x5d2b0c
    ---copy 0x22ff20 to 0x5d2b10
    ---destory sss 0x5d2ae8, value:12
    ---destory sss 0x5d2aec, value:13
    ---destory sss 0x5d2af0, value:14
    ---destory sss 0x5d2af4, value:15
    size: 5, capacity: 8
    ---destory sss 0x5d2b00, value:12
    ---destory sss 0x5d2b04, value:13
    ---destory sss 0x5d2b08, value:14
    ---destory sss 0x5d2b0c, value:15
    ---destory sss 0x5d2b10, value:16
    ---destory sss 0x22ff20, value:16


    结果分析:

    vector 每次调用 push_back 时都会拷贝一个新的参数指定的 sss 类对象,这会调用 sss 的拷贝构造函数,第一次的 copy 正常,而且 vector 的实际容量也由 0  变为 1。

    第二次调用 push_back,通过输出会发现调用了两次拷贝构造函数,一次析构函数,原来 vector 此时判断容量不够,将容量扩大为原来的两倍,变为 2,并将原来的元素再次拷贝一份存放到新的内存空间,然后拷贝新加的类对象,最后再释放原来的元素。

    第三次调用 push_back 时,vector 自动扩大为4,因此拷贝构造函数调用了3次,析构函数调用了2次,程序最终退出了时就析构了 5 次加本身的 sss 类对象一共 6 次。

    参考:

    由此看来,vector 的 push_back 在发现空间不足时自动将空间以 2 的指数增长:0 -> 1 -> 2 -> 4 -> 8 -> 16 -> 32 …

    查找资料后得知,如此设计的主要目的是为了尽可能的减小时间复杂度;如果每次都按实际的大小来增加 vector 的空间,会造成时间复杂度很高,降低 push_back 的速度。

    另外关于 push_back 为什么会执行拷贝构造函数,push_back 的原型为:

    void push_back(const _Ty& _Val)

    参数是以引用方式传递,按说不会拷贝,但 push_back 实际实现中判断空间不足时是调用 insert 函数添加元素:

    void push_back(const _Ty& _Val)
    {
       // insert element at end
       if (size() < capacity())
       #if _HAS_ITERATOR_DEBUGGING
       {
          // room at end, construct it there
          _Orphan_range(_Mylast, _Mylast);
          _Mylast = _Ufill(_Mylast, 1, _Val);
       }
       #else /* _HAS_ITERATOR_DEBUGGING */
          _Mylast = _Ufill(_Mylast, 1, _Val);
       #endif /* _HAS_ITERATOR_DEBUGGING */
       else
          insert(end(), _Val);
    }

    展开全文
  • 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天

    展开全文
  • [C++]vector push_back实现原理

    千次阅读 2016-04-12 21:21:51
    vector push_back实现原理原理:vector是用数组实现,每次执行push_back操作,相当于底层数组实现要重新分配大小(即先free掉原存储,后重新malloc);这种实现体现到vector实现就是每当push_back一个元素,都...

    vector 的 push_back实现原理

    原理:

    vector有预存的内存(capacity),如果存入的元素大于了capacity,就重新分配一个比原来capacity大两倍的内存。

    代码示例:

    //
    //  main.cpp
    //  test
    //
    //  Created by 颜泽鑫 on 4/12/16.
    //  Copyright © 2016 颜泽鑫. All rights reserved.
    //
    
    #include <iostream>
    #include <vector>
    using namespace std;
    class test {
    public:
        string a;
        test(string b) : a(b) {
            cout << "new" << " " << a << endl;
        }
        ~test() {
            cout << "deleted " << a << endl;
        }
    };
    int main(int argc, const char * argv[]) {
        vector<test> array;
        string a = "A";
        array.push_back(test("a"));
        cout << array.capacity() << endl;
        array.push_back(test("b"));
        cout << array.capacity() << endl;
        array.push_back(test("c"));
        cout << array.capacity() << endl;
        array.push_back(test("d"));
        cout << array.capacity() << endl;
        array.push_back(test("f"));
        cout << array.capacity() << endl;
        return 0;
    }
    

    输出:(通过看capacity就能看出其运行原理了)

    new a
    deleted a
    1
    new b
    deleted a
    deleted b
    2
    new c
    deleted b
    deleted a
    deleted c
    4
    new d
    deleted d
    4
    new f
    deleted d
    deleted c
    deleted b
    deleted a
    deleted f
    8
    deleted f
    deleted d
    deleted c
    deleted b
    deleted a
    Program ended with exit code: 0

    网友提问:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    struct test{
        test(char c) :a(c)
        {
            cout << "New " << a << endl;
        }
        ~test()
        {
            cout << "delete " << a << endl;
        }
        char a;
    };
    
    int main()
    {
        vector<test> t;
        for (char c = 'a'; c < 'z' + 1; ++c) {
            t.push_back(c);
            cout << t.capacity() << endl;
        }
        system("pause");
    }

    这样大概就能看明白了吧。

    New a
    delete a
    1
    New b
    delete a
    delete b
    2
    New c
    delete b
    delete a
    delete c
    4
    New d
    delete d
    4
    New e
    delete d
    delete c
    delete b
    delete a
    delete e
    8
    New f
    delete f
    8
    New g
    delete g
    8
    New h
    delete h
    8
    New i
    delete h
    delete g
    delete f
    delete e
    delete d
    delete c
    delete b
    delete a
    delete i
    16
    New j
    delete j
    16
    New k
    delete k
    16
    New l
    delete l
    16
    New m
    delete m
    16
    New n
    delete n
    16
    New o
    delete o
    16
    New p
    delete p
    16
    New q
    delete p
    delete o
    delete n
    delete m
    delete l
    delete k
    delete j
    delete i
    delete h
    delete g
    delete f
    delete e
    delete d
    delete c
    delete b
    delete a
    delete q
    32
    New r
    delete r
    32
    New s
    delete s
    32
    New t
    delete t
    32
    New u
    delete u
    32
    New v
    delete v
    32
    New w
    delete w
    32
    New x
    delete x
    32
    New y
    delete y
    32
    New z
    delete z
    32
    delete z
    delete y
    delete x
    delete w
    delete v
    delete u
    delete t
    delete s
    delete r
    delete q
    delete p
    delete o
    delete n
    delete m
    delete l
    delete k
    delete j
    delete i
    delete h
    delete g
    delete f
    delete e
    delete d
    delete c
    delete b
    delete a
    Program ended with exit code: 0
    展开全文
  • 本文同步自:http://zohead.com/archives/vector-push-back-space-copy/ ...这两天在实际程序中使用 STL vector push_back 类对象时出现问题,偶尔发现 vectorpush_back调用类对象...

    转载自:http://zohead.com/archives/vector-push-back-space-copy/

    这两天在实际程序中使用 STL 的 vector push_back 类对象时出现问题,偶尔发现 vector 在 push_back 时的调用类对象的拷贝构造函数和析构函数有点特别,简单做下分析。

    程序代码:

    cat > test.cpp

    #include <iostream>
    #include <vector>
     
    using namespace std;
     
    struct sss
    {
    public:
        explicit sss(int val) : value(val)
        {
            cout << "---init sss " << this << ", value:" 
            << value << endl;
        }
     
        sss(const sss& org)
        {
            cout << "---copy " << &org << " to " << this << endl;
            value = org.value;
        }
     
        ~sss()
        {
            cout << "---destory sss " << this 
            << ", value:" << value << endl;
        }
      
        int value;
    };
     
    int main(int argc, char ** argv)
    {
        sss s_tmp(11);
        int i = 0;
        vector<sss> vvv;
     
        for (i = 0; i < 5; i++) {
            s_tmp.value++;
            vvv.push_back(s_tmp);
            cout << "size: " << vvv.size() 
            << ", capacity: " << vvv.capacity() << endl;
        }
     
        return 0;
    }
    

    功能很简单,main 中定义一个 sss 类对象和对应的 vector,然后在循环中改类成员的值,并依次 push_back 到 vector 中,类的构造函数、析构函数、拷贝构造函数中都加了对应的打印输出。循环运行了5次,往 vector 中增加了5个类成员。

    实际运行输出如下:

    —init sss 0x22ff20, value:11
    —copy 0x22ff20 to 0x5d2a58

    size: 1, capacity: 1
    —copy 0x5d2a58 to 0x5d2ad8
    —copy 0x22ff20 to 0x5d2adc
    —destory sss 0x5d2a58, value:12

    size: 2, capacity: 2
    —copy 0x5d2ad8 to 0x5d2ae8
    —copy 0x5d2adc to 0x5d2aec
    —copy 0x22ff20 to 0x5d2af0
    —destory sss 0x5d2ad8, value:12
    —destory sss 0x5d2adc, value:13

    size: 3, capacity: 4
    —copy 0x22ff20 to 0x5d2af4

    size: 4, capacity: 4
    —copy 0x5d2ae8 to 0x5d2b00
    —copy 0x5d2aec to 0x5d2b04
    —copy 0x5d2af0 to 0x5d2b08
    —copy 0x5d2af4 to 0x5d2b0c
    —copy 0x22ff20 to 0x5d2b10
    —destory sss 0x5d2ae8, value:12
    —destory sss 0x5d2aec, value:13
    —destory sss 0x5d2af0, value:14
    —destory sss 0x5d2af4, value:15

    size: 5, capacity: 8
    —destory sss 0x5d2b00, value:12
    —destory sss 0x5d2b04, value:13
    —destory sss 0x5d2b08, value:14
    —destory sss 0x5d2b0c, value:15
    —destory sss 0x5d2b10, value:16
    —destory sss 0x22ff20, value:16

    结果分析:

    vector 每次调用 push_back 时都会拷贝一个新的参数指定的 sss 类对象,这会调用 sss 的拷贝构造函数,第一次的 copy 正常,而且 vector 的实际容量也由 0 变为 1。

    第二次调用 push_back,通过输出会发现调用了两次拷贝构造函数,一次析构函数,原来 vector 此时判断容量不够,将容量扩大为原来的两倍,变为 2,并将原来的元素再次拷贝一份存放到新的内存空间,然后拷贝新加的类对象,最后再释放原来的元素。

    第三次调用 push_back 时,vector 自动扩大为4,因此拷贝构造函数调用了3次,析构函数调用了2次,程序最终退出了时就析构了 5 次加本身的 sss 类对象一共 6 次。

    参考:

    由此看来,vector 的 push_back 在发现空间不足时自动将空间以 2 的指数增长:0 -> 1 -> 2 -> 4 -> 8 -> 16 -> 32 …

    查找资料后得知,如此设计的主要目的是为了尽可能的减小时间复杂度;如果每次都按实际的大小来增加 vector 的空间,会造成时间复杂度很高,降低 push_back 的速度。

    另外关于 push_back 为什么会执行拷贝构造函数,push_back 的原型为:

    void push_back(const _Ty& _Val)

    参数是以引用方式传递,按说不会拷贝,但 push_back 实际实现中判断空间不足时是调用 insert 函数添加元素:

    void push_back(const _Ty& _Val)
    {
    // insert element at end
    if (size() < capacity())
    #if _HAS_ITERATOR_DEBUGGING
    {
    // room at end, construct it there
    _Orphan_range(_Mylast, _Mylast);
    _Mylast = _Ufill(_Mylast, 1, _Val);
    }
    #else /* _HAS_ITERATOR_DEBUGGING /
    _Mylast = _Ufill(_Mylast, 1, _Val);
    #endif /
    _HAS_ITERATOR_DEBUGGING */
    else
    insert(end(), _Val);
    }

    vs2017

    class A
    {
    public:
    
    	A() {}
    	A(const A&)
    	{
    		std::cout << "construct" << std::endl;
    	}
    	~A()
    	{
    		std::cout << "~destroy" << std::endl;
    	}
    };
    int main()
    {
    	A a1, a2;
    	vector<A> v;
    	for (int i = 0; i < 10; i++)
    	{
    		v.push_back(a1);
    		cout << v.size() << "   " << v.capacity() << endl;
    		//空间增加是1,2,3,4,6,9,13,19....
    	}
    	return 0;
    }
    
    展开全文
  • 面试中被问到vector的内存增长方式是否自己试过...之后是我关于push_back的自己试验,实验发现,我使用的版本push_back是1.5倍增长的,并不是网上说的两倍,不过这个看源码应该是可以改动的系数,贴上我的实验图片和代
  • vector是如何增长: 为了支持快速随机访问,vector是连续存储。 当添加一个新元素时,如果没有空间容纳新元素,...push_back均摊后时间复杂度为O(1)。 vector只有当达到capacity之后才会扩容。 设倍增因子为m.
  • 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);}}...
  • C++ vector的push_back

    2014-11-24 15:48:49
    1.public member function ...void push_back ( const T& x ); Add element at the end Adds a new element at the end of the vector, after its current last element. The content of this new element i
  • 这里写自定义目录标题欢迎使用Markdown编辑器新改变功能快捷键合理创建标题,有助于目录生成如何改变文本样式插入链接与图片如何插入一段漂亮代码片生成一个适合你列表创建一个表格设定内容居中、居左、...
  •  userList.push_back(...) 和 std::vector<Account> userList(100); for(int i = 0; i < 100; i++)  userList[i] = ....; 这两个有什么区别,性能如何&#...
  • 参考博文 v.emplace_back(“li“);//只调用了一个构造函数 v.emplace_back(People(“li“));//调用了一个构造函数,一个移动构造函数
  • 二维vector1 二维vector2 遍历输出 ...首先我们需要先建立一个一维的vector,紧接着push_back for (int i = 0; i < N; ++i) { vector<int> temp; for (int j = 0; j < M; ++j) { tmp.p
  • vector的push_back()函数的赋值方式

    千次阅读 2010-04-20 11:35:00
    vector的push_back()函数的赋值方式是拷贝整个type类型的数据,而不只是拷贝引用(地址),所以不用担心添加局部变量之后会被自动收回。
  • 研究STL之vector的push_back函数解析

    千次阅读 2012-06-08 22:00:39
    突然对vector的push_back好奇,于是看了一下vector的源码,做了以下总结。技术水平不行,写作水平更不行,没空画图。大家看看指出错误。  1、如果有足够空闲的申请的空间,直接插入到最后,调用了通用的一个函数...
  • vector push_back[转]

    万次阅读 2011-06-07 17:54:00
    这种实现体现到vector实现就是每当push_back一个元素,都要重新分配一个大一个元素存储,然后将原来元素拷贝到新存储,之后在拷贝push_back的元素,最后要析构原有的vector并释放原有内存。 例如: 当主函数...
  • C++ vector 的push_back() 以及 内存释放

    万次阅读 多人点赞 2019-09-27 15:11:45
    向量(Vector)是一个封装了动态大小数组顺序容器(Sequence Container)。跟任意其它类型容器一样,它能够存放各种类型对象。可以简单认为,向量是一个能够存放任意类型动态数组。 二、容器特性 1.顺序...
  • move、forward与右值引用 首先看主函数代码: int main() { CMyString str1 = "aaa"; vector<CMyString> vec;... vec.push_back(str1);... vec.push_back(CMyString("bbb")); // move forwor
  • STL之vector的push_back过程详解

    千次阅读 2018-10-12 01:13:27
    最近,被面试官一道题问倒,很失落,明明看过《STL源码分析》,为啥这种问题还没答好,只能说自己看时候没有仔细去思考。这道题就是标题问题,面试完我重新看了一遍《STL源码分析》中关于这块内容,这里记录...
  • ivec.push_back(ivec.back()); for (auto it = ivec.cbegin(); it != ivec.cend(); ++it) cout << *it << " "; cout << endl; 输出结果: 1 1 今天看《c++ primer》时,说emplace...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,215
精华内容 2,086
关键字:

vector的push_back