实战c++中的vector系列--再谈vector的insert()方法(都是make_move_iterator惹的祸)

Posted 一苇渡江694

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实战c++中的vector系列--再谈vector的insert()方法(都是make_move_iterator惹的祸)相关的知识,希望对你有一定的参考价值。

之前说过了关于vector的insert()方法,把vector B的元素插入到vector A中,vector A中的结果我们可想而知,但是vector B中的元素还会如何?

看看之前写过的程序:

#include <iostream>
#include <vector>

int main ()

  std::vector<int> myvector (3,100);
  std::vector<int>::iterator it;

  it = myvector.begin();
  it = myvector.insert ( it , 200 );

  myvector.insert (it,2,300);

  // "it" no longer valid, get a new one:
  it = myvector.begin();

  std::vector<int> anothervector (2,400);
  myvector.insert (it+2,anothervector.begin(),anothervector.end());

  int myarray [] =  501,502,503 ;
  myvector.insert (myvector.begin(), myarray, myarray+3);

  std::cout << "myvector contains:";
  for (it=myvector.begin(); it<myvector.end(); it++)
    std::cout << ' ' << *it;
  std::cout << '\\n';

  return 0;

现在关心一下别的:注意是insert后,被insert的vector为多少了:

#include <iostream>
#include <vector>

int main()

    std::vector<int> myvector(3, 100);

    std::vector<int> anothervector(2, 400);

    std::cout << "Before insert myvector is:";
    for (auto it = myvector.begin(); it<myvector.end(); it++)
        std::cout << ' ' << *it;
    std::cout << std::endl;

    std::cout << "Before insert anothervector is:";
    for (auto it = anothervector.begin(); it<anothervector.end(); it++)
        std::cout << ' ' << *it;

    std::cout << std::endl;

    myvector.insert(myvector.end(), anothervector.begin(), anothervector.end());

    std::cout << "After insert myvector is:";
    for (auto it = myvector.begin(); it<myvector.end(); it++)
        std::cout << ' ' << *it;

    std::cout << std::endl;

    std::cout << "Now the anothervector is:";
    for (auto it = anothervector.begin(); it<anothervector.end(); it++)
        std::cout << ' ' << *it;

    std::cout << std::endl;

    int myarray[] =  501,502,503 ;
    myvector.insert(myvector.begin(), myarray, myarray + 3);

    std::cout << "After insert myarray[] to myvector,  myvector is:";
    for (auto it = myvector.begin(); it<myvector.end(); it++)
        std::cout << ' ' << *it;

    std::cout << std::endl;

    std::cout << "After insert myarray[] to myvector,  myarray[] is:";
    for (int i = 0; i < 3; i++)
    
        std::cout << ' ' << myarray[i];
    

    return 0;

//输出:
//Before insert myvector is : 100 100 100
//Before insert anothervector is : 400 400
//After insert myvector is : 100 100 100 400 400
//Now the anothervector is : 400 400
//After insert myarray[] to myvector, myvector is : 501 502 503 100 100 100 400 400
//After insert myarray[] to myvector, myarray[] is : 501 502 503

如果你看到此时,你肯定会在心里骂娘,谁还关心vector B,并且vectorB并没有变化。
现在是时候来点猛药了,vector中放智能指针。

之前博客也讲诉过对于vector的元素为智能指针的时候:

#include<iostream>
#include<vector>
#include <memory>
using namespace std;
void display_vector(vector<unique_ptr<int>> &vec);
int main()

    vector<unique_ptr<int>> vec;
    unique_ptr<int> s1(new int(1));
    unique_ptr<int> s2(new int(2));
    unique_ptr<int> s3(new int(3));
    unique_ptr<int> s4(new int(4));
    vec.push_back(std::move(s1));
    vec.push_back(std::move(s2));
    vec.push_back(std::move(s3));
    vec.push_back(std::move(s4));


    unique_ptr<int> s5(new int(5));
    vector<unique_ptr<int>> des_vec;
    des_vec.push_back(std::move(s5));
    des_vec.insert(des_vec.end(), std::make_move_iterator(vec.begin()), std::make_move_iterator(vec.end()));
    display_vector(des_vec);
    cout << "now, des_vec size: " << des_vec.size() << endl;
    cout << "now, vec size: " << vec.size() << endl;

    //display_vector(vec);
    cout << "now, vec size: " << vec.size() << endl;
    for (int i=0; i<vec.size(); i++)
    
        cout << *vec[i] << " ";
    
    return 0;


void display_vector(vector<unique_ptr<int>> &vec)

    for (auto it = vec.begin(); it != vec.end(); it++)
    
        cout << **it << endl;
    

上面代码会崩溃,原因就是vec被insert后 ,vec变得无效了,我们不能对他做什么。。。。。

但是需要明确的是这不是insert造成的,如果copy也会造成这一的结局,其实罪魁祸首就是make_move_iterator

再看程序:

#include <iostream>
#include <list>
#include <vector>
#include <string>
#include <iterator>

int main()

    std::list<std::string> s "one", "two", "three" ;

    std::vector<std::string> v1(s.begin(), s.end()); // copy

    std::vector<std::string> v2(std::make_move_iterator(s.begin()),
        std::make_move_iterator(s.end())); // move

    std::cout << "v1 now holds: ";
    for (auto str : v1)
        std::cout << "\\"" << str << "\\" ";
    std::cout << "\\nv2 now holds: ";
    for (auto str : v2)
        std::cout << "\\"" << str << "\\" ";
    std::cout << "\\noriginal list now holds: ";
    for (auto str : s)
        std::cout << "\\"" << str << "\\" ";
    std::cout << '\\n';

//输出:
//v1 now holds : "one" "two" "three"
//v2 now holds : "one" "two" "three"
//original list now holds : ""

最后再上一个官方程序:

#include <iostream>     // std::cout
#include <iterator>     // std::make_move_iterator
#include <vector>       // std::vector
#include <string>       // std::string
#include <algorithm>    // std::copy

int main() 
    std::vector<std::string> foo(3);
    std::vector<std::string> bar "one","two","three" ;

    std::copy(make_move_iterator(bar.begin()),
        make_move_iterator(bar.end()),
        foo.begin());

    // bar now contains unspecified values; clear it:
    bar.clear();

    std::cout << "foo:";
    for (std::string& x : foo) std::cout << ' ' << x;
    std::cout << '\\n';

    return 0;

* 需要注意:*
* bar.clear();*
因此此时: bar now contains unspecified values; clear it:

以上是关于实战c++中的vector系列--再谈vector的insert()方法(都是make_move_iterator惹的祸)的主要内容,如果未能解决你的问题,请参考以下文章

Support Vector Machine : 再谈泛化误差(Generalization Error)

C++从青铜到王者第九篇:STL之vector类的初识

C++从青铜到王者第十篇:STL之vector类的模拟实现

c++中的vector

再谈QVector与QByteArray——Qt的写时复制(copy on write)技术

利用c++中的vector创建动态二维数组