欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++ STL中的 emplace

程序员文章站 2022-03-21 16:36:43
...

英文释义(以前还真的很少用到这个单词,但是经常在键入empty()函数的时候冒出来):

emplace 
英 [ɪm'pleɪs]   美 [ɪm'pleɪs]  
v. 放列,安置,安放;

相对于insert、push、push_back系列先构造临时变量再复制到目标位置,emplace直接在目标位置上构造了。而且emplace支持“变参模板”,也就是说,如果它的实例类的构造函数有多个参数,emplace也支持对应个数的参数,而且对于显式构造函数,也能直接传参数。

比如这个类,接受一个int型的构造函数

class EmplaceClass {
    int num;
public:
    /*explicit */EmplaceClass(int x = 0) :num(x) { cout << "Constructed.\n"; }
    EmplaceClass(const EmplaceClass& from) :num(from.num) { cout << "Copied.\n"; }
    ~EmplaceClass() {/* cout << "Destructed.\n"; */}
};

在主函数函数中调用时的测试,为了避免vector增长后会复制,所以分别各自的vector进行push_back和emplace_back

    vector<EmplaceClass> ecTest,pbTest;
    cout << "Now emplace one element:" << endl;
    ecTest.emplace_back(1);
    cout << "Now push back one element:" << endl;
    pbTest.push_back(1);

输出为

Now emplace one element:
Constructed.
Now push back one element:
Constructed.
Copied.

emplace操作少了一次复制

当构造函数为显示时

class EmplaceClass {
    int num;
public:
    explicit EmplaceClass(int x = 0) :num(x) { cout << "Constructed.\n"; }
    EmplaceClass(const EmplaceClass& from) :num(from.num) { cout << "Copied.\n"; }
    ~EmplaceClass() {/* cout << "Destructed.\n"; */}
};

编译器就会报错

C++ STL中的 emplace

加入移动构造函数

class EmplaceClass {
    int num;
    string str;
public:
    /*explicit*/ EmplaceClass(int x = 0,string s="") :num(x) ,str(move(s)){ cout << "Constructed.\n"; }
    EmplaceClass(const EmplaceClass& from) :num(from.num),str(move(from.str)) { cout << "Copied.\n"; }
    EmplaceClass(EmplaceClass && from) :num(from.num), str(move(from.str)) { cout << "Moved.\n"; }
    ~EmplaceClass() {/* cout << "Destructed.\n"; */}
};
    vector<EmplaceClass> ecTest,pbTest;
    cout << "Now emplace one element:" << endl;
    ecTest.emplace_back(1,"a");
    cout << "Now push back one element:" << endl;
    //EmplaceClass ec(1, "a");
    //pbTest.push_back(ec);//左值引用
    pbTest.push_back({ 1,"a"});//右值引用

输出为

Now emplace one element:
Constructed.
Now push back one element:
Constructed.
Moved.

其实看看C++17里面push_back函数的源码,就知道原因了:

void push_back(const _Ty& _Val)
		{	// insert element at end, provide strong guarantee
		emplace_back(_Val);
		}

void push_back(_Ty&& _Val)
		{	// insert by moving into element at end, provide strong guarantee
		emplace_back(_STD move(_Val));
		}

相当于先构建一个左值或者右值引用_Val,再调用emplace_back。