C++11/17 中 std::atomic 的间接和直接初始化。有什么区别?

问题描述 投票:0回答:1

在 CPP Con 2017 网络研讨会上,Fedor Pikus 说:“它必须是直接初始化”

这是网络研讨会的链接

这些初始化方法有什么区别? (随后,为什么它必须是“直接”初始化?为什么“间接”初始化是“不是”?)

// C++17 Compiler

#include <atomic>

class Example
{
    std::atomic<bool> m_b1 = false; // 1-h
    std::atomic<bool> m_b2{ false }; // 2-h

    static void doSomethng()
    {
        std::atomic<bool> b1 = false; // 1-f
        std::atomic<bool> b2{ false }; // 2-f
        std::atomic<bool> b3(false); // 3-f

        // Do something
    }
};
c++ c++11 c++17 std stdatomic
1个回答
7
投票

std::atomic
不可复制或移动。

在 C++17 之前,复制初始化

std::atomic<int> x = 0;
将首先从
std::atomic<int>
构造一个临时
0
,然后从该临时值直接初始化
x
。如果没有移动或复制构造函数,这将失败,因此该行无法编译。

然而

std::atomic<int> x(0);
是直接初始化,只会使用构造函数的参数
x
来构造
0

自 C++17 起,就没有临时的了,在任何情况下

x
都将直接由构造函数调用以
0
作为参数来初始化,因此
std::atomic
不存在不可移动的问题。从这个意义上说,这张幻灯片现在已经过时了。

尽管在这种情况下复制初始化和直接初始化的行为现在是相同的,但总的来说两者之间仍然存在差异。特别是直接初始化选择构造函数通过重载决议直接初始化变量,而复制初始化尝试找到隐式转换序列(可能通过具有不同重载决议规则的转换构造函数或转换函数)。此外,与直接初始化相比,复制初始化不考虑标记为

explicit
的构造函数。

关于问题中的代码片段。

1-h
1-f
是如上所述的复制初始化。
3-f
是上面的直接初始化。
2-h
2-f
是直接列表初始化,在某些情况下其行为与其他两者不同,但在这里它与带括号的直接初始化具有相同的效果。

解释一般初始化形式之间的所有差异需要一段时间。众所周知,这是 C++ 最复杂的部分之一。

© www.soinside.com 2019 - 2024. All rights reserved.