【发布时间】:2019-01-05 09:37:12
【问题描述】:
带有成员初始化器列表的代码示例。
#include <memory>
struct Throwable
{
Throwable()
{
throw "Exception!";
}
};
struct A
{
A() : t(Throwable()), i(new int()) {}
Throwable t;
std::unique_ptr<int> i;
};
如果可能有以下评估顺序,我会不会有内存泄漏?
new int()Throwable()t()i()
标准中的顺序是什么?我们有一些规则。
https://en.cppreference.com/w/cpp/language/initializer_list
3) 然后,按照类定义中的声明顺序初始化非静态数据成员。
所以t 将在i 之前构造。
https://en.cppreference.com/w/cpp/language/eval_order
9) 内置逗号运算符
,的第一个(左)参数的每个值计算和副作用在第二个(右)参数的每个值计算和副作用之前排序。
但是成员初始化器列表由于之前的引用没有使用所有的逗号规则。而且它不是逗号运算符 (https://en.cppreference.com/w/cpp/language/operator_other#Built-in_comma_operator)。
10) 在列表初始化中,给定初始化器子句的每个值计算和副作用都排在与任何初始化器子句相关联的每个值计算和副作用之前,该初始化器子句在括号括起来的逗号分隔的初始化器列表中。
还有https://en.cppreference.com/w/cpp/language/list_initialization
列表初始化在以下情况下进行:
5) 如果使用了braced-init-list,则在构造函数的成员初始化列表中
我还有一个案例。
您能否提供定义成员初始化器列表中参数评估顺序的规则?
【问题讨论】:
-
申报顺序?
-
std::make_unique会避免任何“风险”。 -
'评估顺序'。我需要“sequenced-before”(en.cppreference.com/w/cpp/language/eval_order)方面的答案。
-
@JesperJuhl:因为标准是拜占庭式的,而且这是来自实际上设法主要理解其中定义的 C++ 对象模型的人。例如,我希望在定义了成员初始化器列表的 [class.base.init] 中找到这个问题的答案,但它不存在。它显然是在 [intro.execution] 的 10 章之前。为什么?因为它碰巧被一般性陈述而不是特定陈述所涵盖。标准中的信息通常足够分散,因此提出相关问题并非不合理。
-
@JesperJuhl standardese 不一定简单明了。我知道我花了很长时间才达到对阅读标准有信心的地步。即使多年后,有时我仍然很难确定我的解释是正确的。从他的问题中可以看出,他确实在努力寻找答案。虽然“RTFM”可能是对许多问题的有效回答,但我认为“在标准中查找”并不是对合法 C++ 问题的有用回答,尤其是明确询问标准内容的问题……跨度>
标签: c++ c++11 language-lawyer initializer-list member-initialization