From: Peng Yu on 14 Jun 2010 18:05 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? -- Regards, Peng [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Ulrich Eckhardt on 14 Jun 2010 23:09 Peng Yu wrote: > 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.) You are correct. > 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. Actually, I wouldn't say so. I would rather use a std::auto_ptr, as ownership transfer is exactly what I want to express. This saves the overhead of atomic increment/decrement operations for the reference counter and the allocation of the reference counter, both of which are not completely negligible. The only drawback left is that I would like to express via the returned type that the function will not return a null pointer, but neither std::auto_ptr nor boost::shared_ptr support anything like that. > 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? This has two sides, both of which are implementation-defined, so no guarantees are possible. The first side is the inside of the function. It can create the local map in the same place where it would construct the returnvalue, thus saving one copy. The second side is the calling function, which can use the object in the place where it is created by the called function instead of creating a local and copying it there, which saves another copy. Both parts are possible even if the two are compiled completely separated from each other. Note: You mentioned copy on write (COW). There is a very simple way to get that, and that is to use std::auto_ptr<T> and boost::shared_ptr<T const>. If you exclusively own the object (auto_ptr) you may modify it as you want. If you have shared ownership (shared_ptr) you may not modify it but instead have to copy it first. If you assign an auto_ptr to a shared_ptr, the auto_ptr becomes null and the shared_ptr assumes ownership, which can then be shared. This doesn't do the COW automatically behind the scenes, but is very handy if you share large objects that only occasionally need copying. Uli -- Sator Laser GmbH Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932 [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Daniel Krügler on 15 Jun 2010 09:44 On 15 Jun., 21:59, Jeff Flinn <TriumphSprint2...(a)hotmail.com> wrote: > Goran wrote: [..] > > I think so, too, but you have swap method, which is efficient. So: > > > LibMapType map; > > map.swap(LibFuncReturningMap(...)); > > IIRC, that won't compile on gcc 4.0.1 for me(but does with MSVC's > extensions). I need to: > > > LibMapType map; > > LibFuncReturningMap(...).swap(map); Yeah, this is the only correct way, because swap requires a (mutable) lvalue, but above an rvalue was provided. It is a shame, that accepting rvalues at these locations still belong to the default settings of MSVC... Greetings from Bremen, Daniel Kr�gler -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Bo Persson on 15 Jun 2010 23:01 { note to moderators redacted. -mod } Daniel Kr�gler wrote: > On 15 Jun., 21:59, Jeff Flinn <TriumphSprint2...(a)hotmail.com> wrote: >> Goran wrote: > [..] >>> I think so, too, but you have swap method, which is efficient. So: >> >>> LibMapType map; >>> map.swap(LibFuncReturningMap(...)); >> >> IIRC, that won't compile on gcc 4.0.1 for me(but does with MSVC's >> extensions). I need to: >> >>> LibMapType map; >>> LibFuncReturningMap(...).swap(map); > > Yeah, this is the only correct way, because swap requires a > (mutable) lvalue, but above an rvalue was provided. It is a > shame, that accepting rvalues at these locations still belong > to the default settings of MSVC... > Who runs compilers with default settings? :-) Those are permissive enough to minimize the number of support cases for the product. A business optimization. If we compile with the proper setting - highest warning level - the compiler will tell us that "the type conversion is not allowed by the C++ standard". http://msdn.microsoft.com/en-us/library/186yxbac%28VS.80%29.aspx Bo Persson -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
Pages: 1 Prev: Treating Foo<T>* as Foo<const T>* Next: Treating Foo<T>* as Foo<const T>* |