[prev in list] [next in list] [prev in thread] [next in thread]
List: boost-users
Subject: Re: [Boost-users] [assign][ptr_container] Exception safety of ptr_list_of, ptr_push_back, ptr_map_in
From: Gavin Lambert <gavinl () compacsort ! com>
Date: 2014-09-25 0:47:32
Message-ID: lvvon5$rhi$1 () ger ! gmane ! org
[Download RAW message or body]
On 24/09/2014 21:52, Aaron Levy wrote:
> Yes I saw that the documentation says these are exception safe and
understandably the arguments are forwarded to the constructors. I was
just trying to understand the scenarios under which code like the
example below cause exception-safety issues.
>
> boost::ptr_vector<Foo> vec;
> push_back(vec)(new Foo)(new Foo);
>
> My reasoning was that the nth "new Foo" gets evaluated after the n-1
"new Foo" expressions which by then are already part of the container.
That is not correct. The compiler is free to evaluate the independent
subexpressions in any order; it is only constrained by dependent
expressions. For example, the below code is a valid rewrite of the
above by the compiler internals:
boost::ptr_vector<Foo> vec;
Foo *tmp2 = new Foo;
auto tmp3 = push_back(vec);
Foo *tmp1 = new Foo;
auto tmp4 = tmp3(tmp1);
tmp4(tmp2);
In particular note that if the second "new Foo" (to tmp1) throws --
which is possible due to out-of-memory even if for no other reason --
then the pointer in tmp2 will be leaked, as it hasn't yet been assigned
to the container. The same can occur if push_back or if tmp3() throw.
The compiler is free to allocate tmp1 and tmp2 in any order; the only
constraints are:
1. It must call their constructors after the constructor of vec is called.
2. It must create tmp1 before it can call tmp3 to create tmp4.
3. It must create tmp2 before it can call tmp4.
Similarly if there were any parameters being passed to the Foo
constructor (whether using this method or using constructor forwarding),
temporary values for these could be created in any order -- not just out
of parameter order but also not in the order of constructing the objects
they're being passed to.
It's the same principle as this:
f(a(), b(), c(), d());
In the above, the compiler can call a,b,c,d in any order. The only
constraint is that it must call all four of them before it can call f.
_______________________________________________
Boost-users mailing list
Boost-users@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic