C++17中无默认构造函数的类如何使用类内初始化器解决SonarLint警告
报错原因
- 写法
m_foo = Foo("something");触发C2280的核心原因:Foo类包含const修饰的成员变量,编译器会默认删除拷贝赋值、移动赋值运算符,复制初始化语义要求赋值运算符可用,因此编译不通过。即使C++17引入了强制复制消除,部分旧版本VS2019的编译器对类内复制初始化的消除支持存在兼容问题,不推荐这种写法。 - 写法
m_foo(Foo("something"));触发C2064的核心原因:C++语法不允许类内成员初始化使用圆括号形式,该写法会被编译器解析为「声明名为m_foo、参数为Foo类型的成员函数」,和成员变量的定义冲突,因此报错。
正确实现方式
使用C++11及以上标准支持的花括号统一初始化实现类内初始化即可,既符合SonarLint RSPEC-3230规则要求,也不会触发编译错误:
class Bar { private: Foo m_foo{"something"}; // 直接调用Foo的构造函数完成初始化,无拷贝/赋值语义 }; // Bar的构造函数无需再在初始化列表中初始化m_foo,会默认使用类内的初始化值 Bar::Bar() { }
补充说明
如果Bar存在多个构造函数,部分构造需要给m_foo传入自定义值,只需要在对应构造函数的初始化列表中覆盖类内初始化值即可,此时SonarLint不会重复触发警告:
Bar::Bar(const std::string& custom_str) : m_foo(custom_str) { }
内容的提问来源于stack exchange,提问作者user8694474
相关产品推荐
相关产品推荐

