为什么禁用 std::atomic 的复制省略在使用 C++17 时不起作用?
Why disabling copy elision for std::atomic doesn't work using C++17?
对于 std::atomic
复制构造函数被删除,由于 :
这应该只能用 C++17 和更高版本编译
std::atomic<int> t_int = 1;
我预计它不会使用 -fno-elide-constructors
标志进行编译,但它仍然可以编译:
https://godbolt.org/z/nMvG5vTrK
这是为什么?
C++17 并不仅仅说以前可选的 return 值优化现在是强制性的。语言的实际描述发生了变化,因此一开始就不再创建临时对象。
因此,自 C++17 起,不再有 可以 省略的构造函数调用。因此,-fno-elide-constructors
不添加任何临时创建是有道理的。那将违反语言规则。
在 C++17 之前,该语言描述了创建一个临时对象,从中初始化变量,然后添加编译器 允许 省略这个临时对象。因此,无论是否使用 -fno-elide-constructors
,编译器都会通过省略或不省略临时副本来表现出符合标准的行为。
I expected that it does not compile using -fno-elide-constructors flag,
给定标志对 C++17 及以后的 return 值优化(又名 RVO)没有影响。这是因为它不再被视为优化(来自 C++17),而是 语言保证。
Under the following circumstances, the compilers are required to omit the copy and move construction of class objects, even if the copy/move constructor and the destructor have observable side-effects. The objects are constructed directly into the storage where they would otherwise be copied/moved to. The copy/move constructors need not be present or accessible:
- In the initialization of an object, when the initializer expression is a prvalue of the same class type (ignoring cv-qualification) as the variable type:
(强调我的)
这意味着 t_int
是直接从 prvalue
1
构造的。标志 -fno-elide-constructors
对 RVO 没有影响,这与 NRVO 不同。所以被删除的复制构造函数对你的情况没有影响。
也许一个例子可能有助于说明相同的情况,
struct Custom
{
public:
Custom(int p): m_p(p)
{
std::cout<<"converting ctor called"<<std::endl;
}
Custom(const Custom&) = delete; //deleted copy ctor
private:
int m_p = 0;
};
int main()
{
Custom c = 1; //works in C++17 but not in Pre-C++17
}
对于 std::atomic
复制构造函数被删除,由于
std::atomic<int> t_int = 1;
我预计它不会使用 -fno-elide-constructors
标志进行编译,但它仍然可以编译:
https://godbolt.org/z/nMvG5vTrK
这是为什么?
C++17 并不仅仅说以前可选的 return 值优化现在是强制性的。语言的实际描述发生了变化,因此一开始就不再创建临时对象。
因此,自 C++17 起,不再有 可以 省略的构造函数调用。因此,-fno-elide-constructors
不添加任何临时创建是有道理的。那将违反语言规则。
在 C++17 之前,该语言描述了创建一个临时对象,从中初始化变量,然后添加编译器 允许 省略这个临时对象。因此,无论是否使用 -fno-elide-constructors
,编译器都会通过省略或不省略临时副本来表现出符合标准的行为。
I expected that it does not compile using -fno-elide-constructors flag,
给定标志对 C++17 及以后的 return 值优化(又名 RVO)没有影响。这是因为它不再被视为优化(来自 C++17),而是 语言保证。
Under the following circumstances, the compilers are required to omit the copy and move construction of class objects, even if the copy/move constructor and the destructor have observable side-effects. The objects are constructed directly into the storage where they would otherwise be copied/moved to. The copy/move constructors need not be present or accessible:
- In the initialization of an object, when the initializer expression is a prvalue of the same class type (ignoring cv-qualification) as the variable type:
(强调我的)
这意味着 t_int
是直接从 prvalue
1
构造的。标志 -fno-elide-constructors
对 RVO 没有影响,这与 NRVO 不同。所以被删除的复制构造函数对你的情况没有影响。
也许一个例子可能有助于说明相同的情况,
struct Custom
{
public:
Custom(int p): m_p(p)
{
std::cout<<"converting ctor called"<<std::endl;
}
Custom(const Custom&) = delete; //deleted copy ctor
private:
int m_p = 0;
};
int main()
{
Custom c = 1; //works in C++17 but not in Pre-C++17
}