今天做c++ primer题目实现标准库vector,emplace_back忽然发现我对其了解甚少,首先,我在网上找到答案的代码,之前有过了解emplace_back是通过移动构造函数实现的,那么问题来了,如果我想实现vector<Base> b这样,我将其移动构造函数显式删除,那么
b.emplace_back(....),还能工作吗? 答案是 : 能
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//Base.h
#include<string>
class Base
{
public :
Base() = default ;
Base(std::string t, int m):s(t),i(m){}
Base( const Base& b):s(b.s),i(b.i){}
Base(Base&&) = delete ;
private :
std::string s;
int i;
};
|
这似乎符合我们的期望,可当我尝试使用自定义的版本(也就是网上那些"高手"的,还是外国人放在github的,呵呵啦,害我找这么久原因,不是坑吗?) 自定义版本如下:
1
2
3
4
5
6
7
8
|
template < typename T>
template < class ...Args>
void
Vec<T>::emplace_back(Args&& ...args)
{
chk_n_alloc();
alloc.construct(first_free++, std::forward<Args>(args)...);
}
|
补充知识:C++11新特性,推荐使用emplace_back()替换push_back()的原因
c++11新加入了emplace_back()用来替换push_back():
在平时我们习惯性的尾插用push_back()去完成,但是如果是尾插临时对象的话,push_back()需要先构造临时对象,再将这个对象拷贝到容器的末尾,而emplace_back()则直接在容器的末尾构造对象,这样就省去了拷贝的过程。
分析如下代码:
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
|
#include<bits/stdc++.h>
using namespace std;
int i=0,j=0;
class A {
public :
A( int i){
str = to_string(i);
cout << "构造函数" <<++i<< endl;
}
~A(){}
A( const A& a): str(a.str){
cout << "拷贝构造" <<++j<< endl;
}
public :
string str;
};
int main(){
vector<A> vec;
vec.reserve(10); //开辟capacity
for ( int i=0;i<10;i++){
vec.push_back(i); //调用了10次构造函数和10次拷贝构造函数,
// vec.emplace_back(i); //调用了10次构造函数一次拷贝构造函数都没有调用过
}
}
|
以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。如有错误或未考虑完全的地方欢迎留言讨论,望不吝赐教。
原文链接:https://blog.csdn.net/RGBMarco/article/details/70228598