Reputation: 53
Example of a code with a member initializer list.
#include <memory>
struct Throwable
{
Throwable()
{
throw "Exception!";
}
};
struct A
{
A() : t(Throwable()), i(new int()) {}
Throwable t;
std::unique_ptr<int> i;
};
Can I have got a memory leak if there could be the following evaluation order?
new int()
Throwable()
t()
i()
What is the order in the Standard? We have some rules.
https://en.cppreference.com/w/cpp/language/initializer_list
3) Then, non-static data members are initialized in order of declaration in the class definition.
So t
will be constructed before i
.
https://en.cppreference.com/w/cpp/language/eval_order
9) Every value computation and side effect of the first (left) argument of the built-in comma operator
,
is sequenced before every value computation and side effect of the second (right) argument.
But member initializer list does not use all comma rules because of the previous reference. And it is not the comma operator (https://en.cppreference.com/w/cpp/language/operator_other#Built-in_comma_operator).
10) In list-initialization, every value computation and side effect of a given initializer clause is sequenced before every value computation and side effect associated with any initializer clause that follows it in the brace-enclosed comma-separated list of initalizers.
And https://en.cppreference.com/w/cpp/language/list_initialization
List initialization is performed in the following situations:
5) in a member initializer list of a constructor if braced-init-list is used
I have another case.
Could you provide the rule which defines the order of arguments evaluation in a member initializer list?
Upvotes: 3
Views: 373
Reputation: 657
Can I have got a memory leak if there could be the following evaluation order?
The answer is No,
because order of initialization of non-static members is defined as same as order of members declaration within class definition, not related to order in member initializer list, that is because destruction need to be executed in reverse order of construction, in order to achieve that, it has to be rule to follow when destruction start. Regarding that, cause you have declared member of type throwable before any other member, it will be constructed first and throw before heap allocation happened. There is no leak.
But if you declared member of type throwable after unique_pointer declaration, in initialization process heap allocation would happened first, and after that, throwing exception from throwable constructor, will stop A construction, and even if catched, exception will be re-thrown after exception handler execution, but following rule that any constructed class member will be destructed as well, resource management capabilities of unique_pointer will prevent leak, in this scenario as well.
I hope this little observation helps.
Upvotes: 0
Reputation: 15951
No, this evaluation order that would potentially cause you to leak is guaranteed not to happen. The expression within each mem-initializer is a full-expression ([intro.execution] §5.3). And [intro.execution] §9 tells us
Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.
So in other words, the evaluation of each expression used to initialize a member is completed before evaluation of the expression for the next member starts.
Upvotes: 4