使用{*this}初始化类

Wir*_*rie 19 c++ c++11

团队成员建议使用这样的初始化器:

return Demo{ *this };
Run Code Online (Sandbox Code Playgroud)

比以下更好:

return Demo(*this);
Run Code Online (Sandbox Code Playgroud)

假设一个像这样的简单类:

class Demo {
public:
    int value1;
    Demo(){}
    Demo(Demo& demo) {
        this->value1 = demo.value1;
    }
    Demo Clone() {
        return Demo{ *this };
    }
};
Run Code Online (Sandbox Code Playgroud)

我承认以前没有看过{ *this }语法,也找不到足够好的解释,以便我理解这两个选项的不同之处.是否有性能优势,语法选择或更多内容?

Ste*_*eve 16

你的同事错过了"统一初始化"的技巧,知道时不需要输入类型名称.例如,在创建返回值时. Clone可以定义为:

Demo Clone() {
    return {*this};
}
Run Code Online (Sandbox Code Playgroud)

这将Demo根据需要调用复制构造函数.无论你认为这是好还是坏,都取决于你.

GOTW 1 Sutter中指出:

指南:更喜欢使用{}进行初始化,例如向量v = {1,2,3,4}; 或者自动v =向量{1,2,3,4} ;,因为它更一致,更正确,并且避免必须知道旧式陷阱.在单参数情况下,您更喜欢只看到=符号,例如int i = 42; 和自动x =任何东西; 省略括号是好的....

特别是,使用大括号可以避免混淆:

Demo d();      //function declaration, but looks like it might construct a Demo
Demo d{};      //constructs a Demo, as you'd expect
Run Code Online (Sandbox Code Playgroud)

大括号语法将使用一个构造函数,该构造函数首先获取初始化列表(如果存在).否则它将使用普通的构造函数.它还可以防止上面列出的烦恼解析的可能性.

使用复制初始化时也有不同的行为.用标准的方式

Demo d = x;
Run Code Online (Sandbox Code Playgroud)

编译器可以选择在必要时转换x为a Demo,然后将转换后的r值移动/复制到w.类似于Demo d(Demo(x));意味着调用多个构造函数的东西.

Demo d = {x};
Run Code Online (Sandbox Code Playgroud)

这相当于Demo d{x}并保证只调用一个构造函数.由于上述两个赋值都不能使用显式构造函数.

正如评论中所提到的,存在一些陷阱.使用initializer_list具有"正常"构造函数的类会导致混淆.

vector<int> v{5};       // vector containing one element of '5'
vector<int> v(5);       // vector containing five elements.
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢讽刺的是添加一种新语法来避免陷阱,然后添加更多陷阱. (8认同)
  • 但是有一些陷阱.`vector <int> v {5};`将使一个向量成为一个元素,等于5.而`v(5)`将给出五个元素,所有都默认为零.对某些人来说,这似乎令人惊讶或不一致. (3认同)

nvo*_*igt 5

这只是调用复制构造函数的另一种语法(实际上,用于调用构造函数,将大括号中的内容作为参数,在本例中为复制构造函数).

就个人而言,我会说它比以前更糟,仅仅是因为它做同样的事情......它只依赖于C++ 11.因此它增加了依赖性而没有任何好处.但你的里程可能会有所不同 你必须问你的同事.