首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在使用emplace添加到std::map时,如何避免临时副本?

在使用emplace添加到std::map时,如何避免临时副本?
EN

Stack Overflow用户
提问于 2017-08-03 08:01:40
回答 2查看 913关注 0票数 2
代码语言:javascript
运行
复制
#include <iostream>
#include <map>
using namespace std;

struct FooStruct 
{
    int a;
    int b;
};

int main()
{
    map<int, FooStruct> fooMap;
    fooMap.emplace<int, FooStruct>(0, {1, 2});
    return 0;
}

在防止临时拷贝方面,以上是emplace的正确用法吗?上面的形式是否比

代码语言:javascript
运行
复制
fooMap.emplace(make_pair<int, FooStruct>(0, {1, 2}));

或者,这些表单是否等效,并且它们都避免创建FooStruct的临时副本

EN

回答 2

Stack Overflow用户

发布于 2017-08-05 17:41:44

如果您将“正确性”定义为简洁,您可能希望使用std::map::insert而不是std::map::emplace,如下所示:

代码语言:javascript
运行
复制
fooMap.insert({0, {1, 2}});

使用emplace时,您必须像示例中那样显式指定类型,或者在FooStruct中显式定义构造函数,如@Max66所示:

代码语言:javascript
运行
复制
fooMap.emplace(std::piecewise_construct,
    std::forward_as_tuple(0),
    std::forward_as_tuple(1, 2));

(这也缺乏简洁性)。

fooMap.insert({0, {1, 2}});不应与

代码语言:javascript
运行
复制
fooMap.emplace(make_pair<int, FooStruct>(0, {1, 2}));

就创建的对象数量而言,正如@Swift指出的那样,它还使用了std::pair的移动构造函数。

如果“正确”意味着“可编译并在运行时按预期工作”,那么您的两个示例都是正确的。

票数 1
EN

Stack Overflow用户

发布于 2017-08-04 09:51:39

编辑:

在本文讨论的三种表单中,避免不必要副本的表单是@max66提出的表单。下面的代码及其输出实际捕获了这三种形式

代码语言:javascript
运行
复制
#include <iostream>
#include <map>
using namespace std;

struct FooStruct 
{
    FooStruct() 
    { 
        cout << "FooStruct Default Constructor" << endl; 
    }
    FooStruct(const FooStruct& other) 
    {
        this->a = other.a;
        this->b = other.b;
        cout << "FooStruct Copy Constructor" << endl;
    }
    FooStruct(int a, int b)
    {
        this->a = a;
        this->b = b;
        cout << "FooStruct Parametrized Constructor" << endl;
    }
    int a;
    int b;
};

输出:

代码语言:javascript
运行
复制
foo.emplace<int, FooStruct>(0, {1, 2})
FooStruct Parametrized Constructor
FooStruct Copy Constructor
fooMap.emplace(make_pair<int, FooStruct>(1, { 2, 3 }))
FooStruct Parametrized Constructor
FooStruct Copy Constructor
FooStruct Copy Constructor
fooMap.emplace(std::piecewise_construct, std::forward_as_tuple(2), std::forward_as_tuple(2, 4))
FooStruct Parametrized Constructor

============

原始(错误)

我有点懒,在贴出这个问题之前没有试着去深入挖掘。我现在看到这三种形式(第三种形式来自@Max66的注释)都是等价的,因为它们都避免了创建FooStruct的临时副本。

代码语言:javascript
运行
复制
#include <iostream>
#include <map>
using namespace std;

struct FooStruct 
{
    FooStruct() { cout << "FooStruct Default Constructor" << endl; }
    FooStruct(int a, int b) { this->a = a; this->b = b; cout << "FooStruct Parametrized Constructor" << endl; }
    int a;
    int b;
};

int main()
{
    map<int, FooStruct> fooMap;
    fooMap.emplace<int, FooStruct>(0, {1, 2});
    fooMap.emplace(make_pair<int, FooStruct>(1, { 2, 3 }));
    fooMap.emplace(std::piecewise_construct, std::forward_as_tuple(2), std::forward_as_tuple(2, 4));
    return 0;
}

上面的代码(使用Visual C++ 2015构建)生成以下输出:

代码语言:javascript
运行
复制
FooStruct Parametrized Constructor
FooStruct Parametrized Constructor
FooStruct Parametrized Constructor

PS:我确实验证了上面输出中的每一行都对应于上面的一个emplace调用

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45472787

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档