Prev: return value optimization vs. returning a boost::shared_ptr of container
Next: return value optimization vs. returning a boost::shared_ptr of container
From: Nick Hounsome on 14 Jun 2010 23:10 On 15 June, 10:05, Peng Yu <pengyu...(a)gmail.com> wrote: > Hi, > > I heard that most (if not all) containers in C++ standards (including > the upcoming one) and in boost.org do not follow copy on write > semantics. (Please correct me if I'm wrong.) > > Therefore, if I need to construct some container in a function and > return it. I'd better return a shared_ptr of the container rather than > the container itself. For example, should return > boost::shared_ptr<tr1::unordered_map> rather than tr1::unordered_map. > > If there is return value optimization (RVO), I think that I can return > tr1::unordered_map as the compile can optimize away unnecessary coping > in certain cases. But I think that there cases where RVO doesn't help. > For example, if tr1::unordered_map is returned from a function that is > only available in the object format (through linkage), the copying can > not be avoided, right? > > Therefore, I think that it is always safer to return a shared_ptr > rather the contain. Would you please let me know if my understanding > is correct? The new standard has rvalue references which allow efficient transfer of data from rvalues. This is a consumer side "optimization" and only requires the destination to have an rvalue reference constructor. rvalue reference constructors will simply "steal" the data from the temporary rvalue. This is typically just a pointer swap. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Bart van Ingen Schenau on 14 Jun 2010 23:48 On Jun 15, 11:05 am, Peng Yu <pengyu...(a)gmail.com> wrote: > Hi, > > I heard that most (if not all) containers in C++ standards (including > the upcoming one) and in boost.org do not follow copy on write > semantics. (Please correct me if I'm wrong.) > > Therefore, if I need to construct some container in a function and > return it. I'd better return a shared_ptr of the container rather than > the container itself. For example, should return > boost::shared_ptr<tr1::unordered_map> rather than tr1::unordered_map. No, that does not follow. > > If there is return value optimization (RVO), I think that I can return > tr1::unordered_map as the compile can optimize away unnecessary coping > in certain cases. But I think that there cases where RVO doesn't help. > For example, if tr1::unordered_map is returned from a function that is > only available in the object format (through linkage), the copying can > not be avoided, right? No, that is wrong. I do not know of any calling convention where the caller would be affected by the application of RVO in the callee. First, RVO is only useful for 'large' return values (more than fits in one or two registers) and in those cases there are essentially two ways of passing the return value: 1. The caller allocates memory for the return value and communicates that location to the callee 2. The callee allocates memory for the return value and returns that location. In both cases, any copying of return values would be done in the callee, so if (N)RVO gets applied, it only affects the callee. > > Therefore, I think that it is always safer to return a shared_ptr > rather the contain. Would you please let me know if my understanding > is correct? Your understanding is not correct. > > -- > Regards, > Peng > Bart v Ingen Schenau -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Goran on 14 Jun 2010 23:51 On Jun 15, 11:05 am, Peng Yu <pengyu...(a)gmail.com> wrote: > Hi, > > I heard that most (if not all) containers in C++ standards (including > the upcoming one) and in boost.org do not follow copy on write > semantics. (Please correct me if I'm wrong.) > > Therefore, if I need to construct some container in a function and > return it. I'd better return a shared_ptr of the container rather than > the container itself. For example, should return > boost::shared_ptr<tr1::unordered_map> rather than tr1::unordered_map. > > If there is return value optimization (RVO), I think that I can return > tr1::unordered_map as the compile can optimize away unnecessary coping > in certain cases. But I think that there cases where RVO doesn't help. > For example, if tr1::unordered_map is returned from a function that is > only available in the object format (through linkage), the copying can > not be avoided, right? I think so, too, but you have swap method, which is efficient. So: LibMapType map; map.swap(LibFuncReturningMap(...)); You'd have to measure whether another map creation plus swap is faster than going to heap (and also living with shared_ptr overhead). I'd guess that swap is faster. Goran. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Goran on 15 Jun 2010 23:02
On Jun 15, 4:51 pm, Goran <goran.pu...(a)gmail.com> wrote: > On Jun 15, 11:05 am, Peng Yu <pengyu...(a)gmail.com> wrote: > > > > > Hi, > > > I heard that most (if not all) containers in C++ standards (including > > the upcoming one) and in boost.org do not follow copy on write > > semantics. (Please correct me if I'm wrong.) > > > Therefore, if I need to construct some container in a function and > > return it. I'd better return a shared_ptr of the container rather than > > the container itself. For example, should return > > boost::shared_ptr<tr1::unordered_map> rather than tr1::unordered_map. > > > If there is return value optimization (RVO), I think that I can return > > tr1::unordered_map as the compile can optimize away unnecessary coping > > in certain cases. But I think that there cases where RVO doesn't help. > > For example, if tr1::unordered_map is returned from a function that is > > only available in the object format (through linkage), the copying can > > not be avoided, right? > > I think so, too, but you have swap method, which is efficient. So: > > LibMapType map; > map.swap(LibFuncReturningMap(...)); And, if you are hell-bent on ...ahem... "user experience", you could add: inline map_type LibFuncReturningMap(other params) { map_type in; LibFuncReturningMap(in, other params); map_type out; out.swap(in); return out; } IOW, you handle "swap", and NRVO handles said user experience: map_type m(LibFuncReturningMap(other params)); Goran. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |