std::set::insert 使用 initializer_list 初始化带有缺省值的构造函数的 struct 可能存在的坑

源码

#include <iostream>
#include <algorithm>
#include <set>

struct complex {
    int a;
    int b;
    complex(int _a=0,int _b=0){
        a=_a;
        b=_b;
    }
    bool operator<(const complex& t) const {
        return a<t.a;
    }
    bool operator==(const complex& t) const {
        return a==t.a;
    }
};

int main() {
    std::set<complex> aa;
    aa.insert(complex(114,514));
    auto iter = aa.find({114,1919});
    for(auto& i:aa){
        std::cout<<i.a<<" "<<i.b<<std::endl;
    }
    std::cout<<std::endl;
    std::cout<<iter->a<<" "<<iter->b<<std::endl<<std::endl;
    aa.insert({1919,810}); // insert 1919,0 and 810,0 actually
    for(auto& i:aa){
        std::cout<<i.a<<" "<<i.b<<std::endl;
    }
    return 0;
}

运行的结果是:

114 514

114 514

114 514
810 0
1919 0

很明显可以看出,最后的 aa.insert({1919,810}) 操作,实际上插入了两个 complex

最后发现问题实际上出在 initializer_list 上,如果使用 aa.insert(complex(114,514)),这里我们使用常规方式构造了一个 complex 对象,而这一句确实没有出现问题。

但是如果直接使用 aa.insert({1919,810});,这里 insert() 会调用 inline void std::set<complex>::insert(std::initializer_list<complex> __l),这个功能实际上是用于一次性插入多个值的,那么为什么编译器会优先匹配到这个重载呢?

原因

问题就出在这里,complex 的构造函数,使用了缺省值。

complex(int _a=0,int _b=0){
	a=_a;
    b=_b;
}
// 即使_a没有使用缺省,也一样,因为_b用了缺省
complex(int _a,int _b=0){
	a=_a;
    b=_b;
}

这个时候,构造一个 complex 对象,实际上甚至可以用下面的一种写法:

complex a = 114514;

这时会构造出一个 a{a=114514, b=0} 。所以实际上上文中的 aa.insert({1919,810}) 相当于是 aa.insert({complex(1919,0),complex(810,0)}) ,同时插入了两个对象。

如何避免

很简单……

如果使用缺省,那么请这样写:

aa.insert(complex(1919,810));

如果不使用缺省,那么原来的写法 aa.insert({1919,810}) 就等同于 aa.insert(complex(1919,810))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值