C++17 STL MAP [] vs insert vs emplace vs try_emplace

class Book {
public:
    int x;
//    string *y;

    bool operator<(const Book &rhs) const {
        return x < rhs.x;
    }

    bool operator>(const Book &rhs) const {
        return rhs < *this;
    }

    bool operator<=(const Book &rhs) const {
        return !(rhs < *this);
    }

    bool operator>=(const Book &rhs) const {
        return !(*this < rhs);
    }

    ~Book() {
        std::cout << ":"
                  << "default destructor\n";
    }

    Book() {
        std::cout << ":"
                  << "default constructor\n";
    }

    Book(int n) {
        this->x = n;
        std::cout << ":"
                  << "constructor with parameter\n";
    }

    Book(Book &&b) {
        this->x = b.x;
        std::cout << ":"
                  << "move constructor\n";
    }

    Book(const Book &b) {
        this->x = b.x;
        std::cout << ":"
                  << "copy constructor\n";
    }

    Book &operator=(const Book &b) {
        this->x = b.x;
        std::cout << ":"
                  << "copy assigment\n";
        return *this;
    }

    Book &operator=(Book &&b) {
        this->x = b.x;
        std::cout << ":"
                  << "move assignment\n";
        return *this;
    }

};

[] 操作符:

示例:

    map<int, Book> data;
    data[1]=2;
    cout<<"###"<<endl;
    data[1]=200;

结果:

:constructor with parameter
:default constructor
:move assignment
:default destructor
###
:constructor with parameter
:move assignment
:default destructor
:default destructor

总结:

key不存在时:会先构造一个默认value对象。然后调用赋值运算符,将参数中的value move过去。

key存在时:调用赋值运算符,将参数中的value  move过去。

insert:

示例:

    map<int, Book> data;
    data.insert(make_pair(1,1));
    cout<<"###"<<endl;
    data.insert(make_pair(1,2));
    cout<<data[1].x<<endl;

结果:

:constructor with parameter
###
:constructor with parameter
:default destructor
1
:default destructor

总结:

key不存在时:

在C++11里面,原地构造了一个value

key存在时:

在C++11里面,原地构造了一个value,但并未实际更新容器。

emplace:

    map<int, Book> data;
    data.emplace(1, 1);
    cout<<"###"<<endl;
    data.emplace(1, 2);
    cout<<data[1].x<<endl;

结果:

:constructor with parameter
###
:constructor with parameter
:default destructor
1
:default destructor

总结:

key不存在时:

在C++11里面,原地构造了一个value

key存在时:

在C++11里面,原地构造了一个value,但并未实际更新容器。

输出与insert一样。实际gcc 中,insert就是用emplace实现的。

try_emplace:

    map<int, Book> data;
    data.try_emplace(1,1);
    data.try_emplace(1,2);
    cout<<data[1].x<<endl;

输出:

:constructor with parameter
1
:default destructor

总结:

key不存在时:

在C++11里面,原地构造了一个value

key存在时:

不构造任何value对象。

insert_or_assign:

map<int, Book> data;
data.insert_or_assign(1,1);
cout<<"###"<<endl;
data.insert_or_assign(1,2);
cout<<data[1].x<<endl;

输出:

:constructor with parameter
###
:constructor with parameter
:move assignment
:default destructor
2
:default destructor

总结:

key不存在时:

在C++17里面,原地构造了一个value

key存在时:

更新了value对象。

最后的总结:

如果map中的数据插入后不需要更新,应该选择try_emplace方式。

如果map中的数据随时可能更新,应该选择insert_or_assign方式。(其实全部场合用insert_or_assign 更安全,他本质上是个不构造临时对象的  operator [])

环境:

ubuntu 22.04

gcc 11

-std=c++17

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值