1、这里需要注意凡是连续空间的容器都提供operator[],[]是为了数组操作
2、back()应该是*(end()-1)!!!
3、vector的大小为12;
vector的迭代器为指针
1. emplace_back
1. 相比push_back,如果传入临时对象T(1),则没有区别,都会调用emplace_back,并通过move,如果传入1,那么push_back则需要两步,先构造函数,再move,而emplace_back则只需要最后调用构造函数
2. 由于其构造函数的特殊性,支持传入多个参数,通过默认构造函数生成右值,并完成构造(push_back也可以)
3. 与push_back的区别在于,构造应在容器中完成,而非在容器外完成,所以不需要move或者拷贝构造!
#include <vector>
#include <iostream>
using namespace std;
class T
{
public:
T(int i){cout<<"111111111"<<endl;};
T(const T& t){cout<<"222222222"<<endl;}
T( T&& t){cout<<"333333333"<<endl;}
};
int main()
{
vector<T> va;
va.reserve(100);
va.push_back(1);
cout<<"~~~~~~~~~~"<<endl;
va.emplace_back(1);
}
PS C:\C++\test> cd "c:\C++\test\" ; if ($?) { g++ a.cpp -o a } ; if ($?) { .\a }
111111111
333333333
~~~~~~~~~~
111111111
可见其只是少了一个构造而已
查了下源码,跳过中间一堆的forward与move,最后区别就在这个placement NEW
- push_back由于在传入前已经隐形类型转换,构造好了。所以这里是走的拷贝构造或者move
- emplace_back如果传入已经构造好的,T(i),那么与push_back类似
-
emplace_back如果传入构造T所需的入参i等,那么这里只是走构造函数而已
class Test
{
public:
Test(Test&& t)
{
cout<<"apple"<<endl;
}
Test(const Test& t) = default;
Test(int i){cout<<"banana"<<endl;};
// Test(const Test&) = delete;
};
template<class T>
unique_ptr<T> fun(T a)
{
auto p = unique_ptr<T>(new T(a));
return p;
}
Test funT(int t)
{
Test tt = Test(t);
return tt;
}
int main()
{
auto a = fun(1);
Test s = funT(1);
vector<Test> t;
t.reserve(10);
t.emplace_back(2); //构造二次
t.push_back(3); // 构造一次,move一次
return 0;
banana
banana
banana
apple
class C3{
public:
C3(){}
C3(int ii,string ss):i(ii),s(ss){cout << " constructor " << endl;}
C3(const C3& c):i(c.i+100),s(c.s + "hhhhhhhhhhh"){cout << " copy constructor " << endl;}
int i;
string s;
};
main 函数:
vector <C3> vC;
vC.push_back(C3(1,"ss"));
cout << vC[0].i << endl;
cout << endl;
vC.emplace_back(3,"kk");
cout << vC[1].i << " " << vC[0].i << endl;
输出:
constructor
copy constructor
101
constructor
copy constructor
3 201
2. begin函数
函数原型:
iterator begin();
const_iterator begin();
功能:
返回一个当前vector容器中起始元素的迭代器。
3. end函数
函数原型:
iterator end();
const_iterator end();
功能:
返回一个当前vector容器中末尾元素的迭代器。
4.front函数
函数原型:
reference front();
const_reference front();
功能:
返回当前vector容器中起始元素的引用。
5.back函数
函数原型:
reference back();
const_reference back();
功能:
返回当前vector容器中末尾元素的引用。
6.reserve和resize
- vector 的reserve增加了vector的capacity,但是它的size没有改变!
- resize改变了vector的capacity同时也增加了它的size!
原因如下:
reserve是容器预留空间,但在空间内不真正创建元素对象,所以在没有添加新的对象之前,不能引用容器内的元素。加入新的元素时,要调用push_back()/insert()函数。
resize是改变容器的大小,且在创建对象,因此,调用这个函数之后,就可以引用容器内的对象了,因此当加入新的元素时,用operator[]操作符,或者用迭代器来引用元素对象。此时再调用push_back()函数,是加在这个新的空间后面的。
vector<int> myVec;
myVec.reserve( 100 ); // 新元素还没有构造,
// 此时不能用[]访问元素
for (int i = 0; i < 100; i++ )
{
myVec.push_back( i ); //新元素这时才构造
}
myVec.resize( 102 ); // 用元素的默认构造函数构造了两个新的元素
myVec[100] = 1; //直接操作新元素
myVec[101] = 2;
不管是调用resize还是reserve,二者对容器原有的元素都没有影响。