关于vector使用的优化
1 class A { 2 public: 3 int m_x; 4 5 A(int x) 6 : m_x(x) 7 { 8 std::cout << "A(int )" << std::endl; 9 } 10 A(const A& a) 11 : m_x(a.m_x) 12 { 13 std::cout << "A(const A&)" << std::endl; 14 } 15 };
1 void solve() 2 { 3 std::vector<A > v; 4 v.push_back(A(1)); 5 v.push_back(A(2)); 6 v.push_back(A(3)); 7 }
1 output: 2 3 A(int) 4 A(const A&) 5 A(int) 6 A(const A&) 7 A(const A&) 8 A(int) 9 A(const A&) 10 A(const A&) 11 A(const A&)
对于上述结果 v.push_back(A(i)),进行了三步操作
①A(1) 创建匿名实例
②对于该匿名实例,v中第一块未使用的内存实行" A(const A& a) ",拷贝构造操作
③vector申请的内存是动态改变的,如果 v 执行 push_back操作,发现申请的内存已满,则会申请一块比原先内存大的连续内存,然后依次进行拷贝构造,之后抛弃原先的内存
从③可以得知,我们如果知识生气了一个vector,不设置其申请的内存大小,则它会依据压入数据大小动态申请,拷贝,抛弃原先内存的操作,
如果我们得知我们需要大概的 int 个数,则我们可以手动设置vector的大小,防止vector申请内存不够而出现上述情况
1 void solve() 2 { 3 std::vector<A > v; 4 v.reserve(3); 5 //v.resize(3) 是初始化v中存在3个A的实例 6 v.push_back(A(1)); 7 v.push_back(A(2)); 8 v.push_back(A(3)); 9 }
1 output: 2 A(int) 3 A(const A&) 4 A(int) 5 A(const A&) 6 A(int) 7 A(const A&)
可以从 output 看出,我们确实优化了vector相关内存和拷贝操作
进一步,从①②中可以,我们其实额外申请了内存,然后再对vector的内存对申请的临时的实例拷贝构造,然后丢弃临时实例,这样不省事也不省时
为了解决这个情况,vector 提供了 emplace_back函数,实现直接对vector中对未使用的内存进行初始化构造操作,传入的数值对应于初始化列表或者根据有参构造函数进行操作
1 void solve() 2 { 3 std::vector<A > v; 4 v.reserve(3); 5 //v.resize(3) 是初始化v中存在3个A的实例 6 v.emplace_back(1); 7 v.emplace_back(2); 8 v.emplace_back(3); 9 10 //for (auto& x : v) std::cout << x.m_x << " " << x.m_y << std::endl; 11 }
output: A(int) A(int) A(int)
这样,我们使用vector时,效率会高很多,而且优化也不会很复杂
1