c++的emplace函数

合集下载

顺序容器一览

顺序容器一览

添加元素操作C.PUSH_BACK(T)C.EMPLACE_BACK(ARG)C.PUSH_FRONT(T)C.EMPLACE_FRONT(ARG)C.INSERT(ITERATOR, VALUE) 在迭代器ITERATOR之前插入值为VALUE的元素C.EMPLACE(ITERATOR, ARG)C.INSERT(ITERATOR, NUMBER, VALUE)C.INSERT(ITERATOR, BEGIN, END) BEGIN和END不能指向C中的元素C.INSERT(ITERATOR, IL )①向VECTOR, STRING, DEQUE中插入元素会使得所有指向容器的迭代器,引用,指针失效②PUSH_FRONT操作可以用C.INSERT(C.BEING(), VALUE)操作来等价实现。

这样插入到VECTOR、STRING和DEQUE中是合法的,但是这样可能很耗时③Emplace 是C++11新标准,与insert不同之处是他是利用构造函数创建的对象,而insert是拷贝已有的对象。

他等价于构造一个临时对象然后用insert访问元素操作:C.POP_BACK()C.POP_FRONT()C.CLEAR() 返回VOIDC.ERASE(ITERATOR) 返回指向被删元素之后的一个迭代器C.ERASE(BEGIN,END) 删除BEGIN到END范围的所有元素,返回指向END之后的元素的迭代器,如果END本身就是尾后元素,那返回的还是尾后元素①删除deque中的除了首尾的元素会是所有迭代器、引用、指针失效②删除vector和string中的元素会使删除点之后的所有迭代器、引用、指针失效③删除之前确保被删除的元素是存在的。

这是由程序员来保证的访问操作:①At成员c.at(n) 下标操作:c[n] 只能用于支持随机访问的vector、string、deque、array。

At在数组越界之后会抛出一个out_of_range异常②Front()成员返回首元素的引用back()成员返回尾元素的引用。

C++11vector使用emplace_back代替push_back

C++11vector使用emplace_back代替push_back

C++11vector使⽤emplace_back代替push_backC++11中,针对顺序容器(如vector、deque、list),新标准引⼊了三个新成员:emplace_front、emplace和emplace_back,这些操作构造⽽不是拷贝元素。

这些操作分别对应push_front、insert和push_back,允许我们将元素放置在容器头部、⼀个指定位置之前或容器尾部。

当调⽤push或insert成员函数时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中。

⽽当我们调⽤⼀个emplace成员函数时,则是将参数传递给元素类型的构造函数。

emplace成员使⽤这些参数在容器管理的内存空间中直接构造元素。

emplace函数的参数根据元素类型⽽变化,参数必须与元素类型的构造函数相匹配。

emplace函数在容器中直接构造元素。

传递给emplace 函数的参数必须与元素类型的构造函数相匹配。

其它容器中,std::forward_list中的emplace_after、emplace_front函数,std::map/std::multimap中的emplace、emplace_hint函数,std::set/std::multiset中的emplace、emplace_hint,std::stack中的emplace函数,等emplace相似函数操作也均是构造⽽不是拷贝元素。

emplace相关函数可以减少内存拷贝和移动。

当插⼊rvalue,它节约了⼀次move构造,当插⼊lvalue,它节约了⼀次copy构造。

下⾯是从其他⽂章中copy的测试代码,详细内容介绍可以参考对应的reference:#include "emplace.hpp"#include <iostream>#include <vector>#include <string>#include <map>#include <tuple>#include <utility>namespace emplace_ {/////////////////////////////////////////////////////////// reference: /reference/vector/vector/emplace_back/int test_emplace_1(){{/*template <class... Args>void emplace_back (Args&&... args);*/std::vector<int> myvector = { 10, 20, 30 };myvector.emplace_back(100);myvector.emplace_back(200);std::cout << "myvector contains:";for (auto& x : myvector)std::cout << '' << x;std::cout << '\n';}{/*template <class... Args>iterator emplace (const_iterator position, Args&&... args);*/std::vector<int> myvector = { 10, 20, 30 };auto it = myvector.emplace(myvector.begin() + 1, 100);myvector.emplace(it, 200);myvector.emplace(myvector.end(), 300);std::cout << "myvector contains:";for (auto& x : myvector)std::cout << '' << x;std::cout << '\n';}return0;}///////////////////////////////////////////////////////// reference: /w/cpp/container/vector/emplace_backnamespace {struct President {std::string name;std::string country;int year;President(std::string p_name, std::string p_country, int p_year): name(std::move(p_name)), country(std::move(p_country)), year(p_year){std::cout << "I am being constructed.\n";}President(President&& other): name(std::move()), country(std::move(other.country)), year(other.year){std::cout << "I am being moved.\n";}President& operator=(const President& other) = default;};}int test_emplace_2(){/*The following code uses emplace_back to append an object of type President to a std::vector.It demonstrates how emplace_back forwards parameters to the President constructor and showshow using emplace_back avoids the extra copy or move operation required when using push_back.*/std::vector<President> elections;std::cout << "emplace_back:\n";elections.emplace_back("Nelson Mandela", "South Africa", 1994);std::vector<President> reElections;std::cout << "\npush_back:\n";reElections.push_back(President("Franklin Delano Roosevelt", "the USA", 1936));std::cout << "\nContents:\n";for (President const& president : elections) {std::cout << << " was elected president of "<< president.country << " in " << president.year << ".\n";}for (President const& president : reElections) {std::cout << << " was re-elected president of "<< president.country << " in " << president.year << ".\n";}return0;}////////////////////////////////////////////////////////////////// reference: https:///questions/4303513/push-back-vs-emplace-backint test_emplace_3(){/*template <class... Args>pair<iterator,bool> emplace (Args&&... args);*/typedef std::tuple<int, double, std::string> Complicated;std::map<int, Complicated> m;int anInt = 4;double aDouble = 5.0;std::string aString = "C++";// cross your finger so that the optimizer is really good//m.insert(/*std::make_pair*/std::pair<int, Complicated>(4, Complicated(anInt, aDouble, aString)));m.insert(std::make_pair(4, Complicated(anInt, aDouble, aString)));// should be easier for the optimizerm.emplace(6, Complicated(anInt, aDouble, aString));/*std::piecewise_construct: This constant value is passed as the first argument to construct a pair object to select the constructor form that constructs its members in place by forwarding the elements of two tuple objects to their respective constructor.*/m.emplace(std::piecewise_construct, std::make_tuple(8), std::make_tuple(anInt, aDouble, aString)); return0;}//////////////////////////////////////////////////////////////// reference: https:///difference-between-emplace_back-and-push_back-function/ namespace {class Dat {int i;std::string ss;char c;public:Dat(int ii, std::string s, char cc) :i(ii), ss(s), c(cc) { }~Dat() { }};}int test_emplace_4(){std::vector<Dat> vec;vec.reserve(3);vec.push_back(Dat(89, "New", 'G')); // efficiency lesser//vec.push_back(678, "Newer", 'O'); // error,push_back can’t accept three arguments vec.emplace_back(890, "Newest", 'D'); // work fine, efficiency is also morereturn0;}} // namespace emplace_。

variant调用emplace例子

variant调用emplace例子

变体是C++11引入的一个新特性,它允许程序员定义一组相关的类型,每个类型都可以具有不同的值。

在C++17中,引入了一个名为emplace的新函数,它可以更方便地将值插入到varant对象中。

本文将围绕variant调用emplace的例子进行讨论,帮助读者更好地理解这一特性。

1. 什么是变体(variant)变体是C++标准库中的一种类型,它可以存储多个不同类型的值,但同时只能存储其中的一个。

一个使用variant的变量可以存储int、double、string等多种类型的值,但在同一时间只能存储其中的一种。

这使得variant成为一个非常灵活的数据类型,特别适合那些需要在不同类型间切换的场景。

2. variant调用emplace的作用在之前的C++标准中,往一个variant对象中插入新值是比较繁琐的,需要使用一些特定的语法和模板。

而在C++17中引入的emplace函数,则可以更加方便地实现这一功能。

通过调用emplace,可以在variant中直接构造存储的值,而不需要显式地指定要存储的类型。

3. variant调用emplace的例子下面将通过一个具体的例子来演示variant调用emplace的用法。

假设我们有一个variant对象用于存储int和string类型的值,现在需要往这个variant中插入一个新的string值,我们可以使用emplace函数来实现:```cpp#include <variant>#include <string>#include <iostream>int m本人n(){std::variant<int, std::string> myVariant;// 使用emplace插入一个string值myVariant.emplace<std::string>("Hello, variant!");// 输出存储的值if (auto pval = std::get_if<std::string>(myVariant)) {std::cout << "存储的值是:" << *pval << std::endl;}return 0;```在这个例子中,首先我们创建了一个variant对象myVariant,它可以存储int和string类型的值。

stl的emplace函数

stl的emplace函数

`emplace`是C++标准模板库(STL)中的一个函数,它用于在容器的指定位置直接构造元素,而不是像`insert`或`push_back`那样先构造然后插入。

使用`emplace`可以避免额外的拷贝或移动操作,从而提高性能。

以下是`emplace`函数的一些基本用法:
1. `std::vector::emplace_back`: 用于在向量的末尾直接构造元素。

```cpp
std::vector<int> v;
v.emplace_back(1, 2, 3); // 构造一个int类型的元素,值为1,2,3
```
2. `std::map::emplace`: 用于在map的指定位置直接构造元素。

```cpp
std::map<std::string, int> m;
m.emplace("one", 1); // 在map中构造一个键为"one",值为1
的元素
```
3. `std::set::emplace`: 用于在set的指定位置直接构造元素。

```cpp
std::set<int> s;
s.emplace(1); // 在set中构造一个值为1的元素
```
使用`emplace`函数时,应尽可能提供与要构造的元素类型匹配的参数,以避免额外的类型转换。

例如,如果你有一个接受两个int参数的构造函数,那么在调用`emplace`时也应提供两个int参数,而不是一个包含这两个int的复杂类型。

emplace c++

emplace c++

emplace c++使用c++三四年了,说实话emplace,今天才是第一次接触,有一种想见恨晚的感觉。

先看看代码,看看结果,你就知道它的妙处!# include <iostream> # include <list> using namespace std ; class TyData { public : TyData ( int a , int b ) { x = a ; y = b ; cout<< "这是构造函数" ; } TyData ( const TyData & d ) { cout << "这是复制构造函数" ; x = d . x ; y = d . y ; } void showTydata ( ){ cout << "x:" << x << " y:" << y << endl ; } private : int x ; inty ; } ; void main ( ) { cout << "use emplace :(parameter)" ; std :: list < TyData > m_emplace_list ; m_emplace_list . emplace_back ( 1 , 2 ) ; m_emplace_list . emplace_back ( 3 , 4 ) ;m_emplace_list . emplace_back ( 5 , 6 ) ; m_emplace_list . emplace_back ( 7 , 8 ) ; m_emplace_list . emplace_back ( 9 , 10 ) ; cout << "not use emplace but objec:" << endl ; TyData d1 ( 11 ,12 ) ; TyData d2 ( 13 , 14 ) ; TyData d3 ( 15 , 16 ) ; TyData d4( 17 , 18 ) ; TyData d5 ( 19 , 20 ) ; std :: list < TyData > m_stlist ;m_stlist . push_back ( d1 ) ; m_stlist . push_back ( d2 ) ; m_stlist . push_back ( d3 ) ; m_stlist . push_back ( d4 ) ; m_stlist .push_back ( d5 ) ; system ( "pause" ) ; }运行结果:从运行结果可以看出:使用emplace比常规的push_back少调用了一次复制构造函数。

c++的set中emplace函数

c++的set中emplace函数

c++的set中emplace函数emplace函数是C++标准库中set容器类的一种成员函数,用于向set中插入新元素。

与insert函数不同的是,emplace函数可以直接在set中构造新元素,而不需要创建临时对象。

这样可以避免额外的拷贝和移动操作,提高了程序的执行效率。

emplace函数的签名如下:```cpptemplate <class... Args>pair<iterator, bool> emplace(Args&&... args);```这个函数接受任意数量的参数,并将它们传递给set中元素的构造函数。

也就是说,通过emplace函数可以直接在set中构造新元素,而不需要先创建一个临时对象。

这对于那些没有默认构造函数的元素类来说尤为有用。

向set中插入新元素有两种可能的结果,一种是插入成功,返回一个指向新插入元素的迭代器和true;另一种是插入失败,返回一个指向已存在元素的迭代器和false。

因此,emplace函数会返回一个pair对象,其中包括插入结果和插入的迭代器。

emplace函数的使用场景很多,比如在set中插入自定义类型的对象。

假设有一个自定义类型Person:```cppclass Person {public:Person(int id, const string& name) : id(id), name(name) {} int id;string name;};```想要向set中插入新的Person对象,可以使用emplace函数:```cppset<Person> personSet;personSet.emplace(1, "Alice");personSet.emplace(2, "Bob");```这样就可以直接在set中构造新的Person对象,而不需要先创建一个临时对象。

c emplace 函数

c emplace 函数

c emplace 函数c++11引入了emplace系列函数,其中emplace_back是vector中最常用的函数。

和push_back区别是emplace_back并不是直接在vector的尾部构造一个新的对象,emplace_back并没有将新建的元素插入到vector的最后,而是就地构造一个新的元素,它的实现过程是在vector的最后一个元素部分性地就地构造一个新的元素。

因此,emplace_back通常比push_back更高效,因为不需要额外的拷贝操作,特别是对于不可拷贝但可移动的对象(例如std::mutex),emplace_back更具优势。

而emplace函数可以用于任何STL容器,用于在容器中构造新元素,其效率比传统的insert函数更高,尤其是对于非POD类型。

emplace函数将按照给定的参数直接在容器中构造在对象,而不是先构造一个临时对象然后再拷贝或移动到容器中。

因此,它可以仅仅执行一次内存分配和对象构造操作,与直接使用对象构造函数非常相似,这样就节省了许多不必要的中间步骤。

这些位置直接大多数时候比拷贝或移动更快,尤其是在某些环境中,例如使用大量小对象的情况下。

emplace函数的使用方式与emplace_back十分相似,我们可以在emplace函数中直接传递一串初始化列表,用于构造新的元素,这个过程将由emplace函数直接处理,而不是通过在容器外部为新元素构造一个临时对象,然后再将其插入容器。

由于emplace是直接在容器中构造一个新对象,因此使用这个函数的时候需要对容器本身的构造方法较为熟悉。

例如,若使用emplace向一个set中添加新元素,那么需要了解set的内部结构(红黑树)和其元素比较规则(operator<),以此来清晰展示emplace函数操作的具体过程。

总结这些,emplace是STL中高效构造新元素的函数之一,通过这一函数,我们可以在容器内部直接构造新元素,避免了不必要的中间拷贝,从而提高了程序的运行效率。

unordered_map emplacec++ 用法

unordered_map emplacec++ 用法

在C++中,unordered_map的emplace函数是一个非常高效的插入方法,因为它可以在容器内部直接构造元素,避免了临时对象的创建和复制。

以下是如何使用unordered_map的emplace方法的一些示例:
cpp代码:
注意以下几点:
1. emplace的第一个参数是键值对的键,后面的参数用于在容器内部直接构造值。

2. 如果插入过程中发生哈希冲突,emplace会自动处理冲突解决。

3. 如果插入的键已经存在,那么原有的元素不会被替换,新插入的元素会被忽略(除非你显式地调用insert_or_assign或try_emplace)。

与insert方法相比,emplace通常更高效,因为它避免了临时对象的创建和可能的复制操作。

然而,如果你已经有了一个完整的键值对对象或者只需要插
入一个简单的值,那么使用insert或者下标运算符[]可能更加简洁。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

c++的emplace函数
emplace函数是C++11标准新增的一个成员函数,用于在容器中直接构造元素。

和insert函数不同,emplace函数直接在容器的内部进行构造,而不是从外部构造好元素再插入容器。

emplace函数需要传入一个完美转发的参数包,用于构造元素。

例如,在一个vector容器中使用emplace函数可以这么写:
```c++
vector<pair<int, string>> v;
v.emplace_back(1, 'first');
```
上述代码会在v容器的末尾直接构造一个pair<int, string>类型的元素。

emplace_back函数会将参数1和'first'完美转发到
pair<int, string>的构造函数中,进行元素的构造。

与insert函数相比,emplace函数更加高效,因为它避免了元素的拷贝或移动操作。

如果元素类型没有定义拷贝或移动构造函数,使用emplace函数则可以避免编译错误。

然而,使用emplace函数也有一些需要注意的地方。

例如,当容器中的元素类型为指针时,需要注意指针的生命周期问题,确保指针指向的对象在容器的整个生命周期内都是有效的。

此外,由于容器中的元素是在容器内部构造的,因此无法在元素构造完毕后再进行一些额外的操作。

如果需要这样的操作,可以考虑使用insert函数或手动构造元素再插入容器。

相关文档
最新文档