|
Prev: delete construct
Next: A question about allocating many std::string and another one about profiling stl memory allocation
From: Alberto Ganesh Barbati on 28 Mar 2008 20:04 Carl Barron ha scritto: > In article <47ebc3fb$0$14342$e4fe514c(a)news.xs4all.nl>, Niels Dekker - > no return address <noreply(a)this.is.invalid> wrote: > >> const std::string & constFoo = doManipulation("bar"); >> >> And if the user needs to have non-const access to the returned string, she can >> still avoid copying, by swapping the result: >> >> std::string nonConstFoo; >> doManipulation("bar").swap(nonConstFoo); > but std::basic_string<...>::swap(std::basic_string < ...> &) is a > non const member function and should the swap code should fail to > compile:) > It does compile. It's true that rvalues cannot be bound to non-const references, but you *can* apply a non-const member function to an rvalue. This is a well-known asymmetry between doManipulation("bar").swap(nonConstFoo); // ok which compiles, as opposed to std::swap(doManipulation("bar"), nonConstFoo); // illegal in C++03 which doesn't (*). The use of the swap() member wouldn't compile only if you declared doManipulation() to return a const std::string but Niels Dekker specifically suggested to avoid that and I totally agree with him. HTH, Ganesh (*) BTW, C++0x will fix that: we will finally be able to call std::swap() between an lvalue and an rvalue, provided the type has a suitable move constructor. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Min-Yu Yang on 28 Mar 2008 23:13 "Niels Dekker - no return address" <noreply(a)this.is.invalid> wrote in message news:47ebc3fb$0$14342$e4fe514c(a)news.xs4all.nl... > Michael (jeungster) wrote: >> >> std::string doManipulation( const std::string & input ); > > Even if the compiler doesn't do RVO, the caller can still avoid the extra > copying by binding the result to a const reference: > > const std::string & constFoo = doManipulation("bar"); What's the lifetime of the temporary std:string object returned by doManipulation? Does the standard guarantee that constFoo still references a valid object after this statement? Even if the standard guarantees that, the above code is risky because some unknowing programmer may return that constFoo to a outer scope, which will have undefined behavior because the temp string for sure will have been destroyed. Min-Yu -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Niels Dekker - no return address on 29 Mar 2008 04:47 >> std::string nonConstFoo; >> doManipulation("bar").swap(nonConstFoo); Carl Barron wrote: > but std::basic_string<...>::swap(std::basic_string < ...> &) is a > non const member function and [so] the swap code should fail to > compile:) Excuse me, but you're wrong! The OP, Michael, declared doManipulation as follows: > std::string doManipulation( const std::string & input ); It's perfectly fine to call a non-const member function of the temporary object, returned by doManipulation. Because the return type of doManipulation is itself non-const! In fact this is an exception to the general guideline, "Use const whenever possible", by Scott Meyers, Effective C++. www.informit.com/content/images/0201924889/items/item21.html Fortunately Scott has recently added a note an his errata page, www.aristeia.com/BookErrata/ec++3e-errata.html: > [...] cases where non-const by-value returns are good design are not > difficult to find, e.g., return types of std::vector<T> where callers > will use swap with an empty vector to "grab" the return value contents > without copying them. Kind regards, Niels -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Nevin :-] Liber on 29 Mar 2008 06:43 In article <fcb00168-7ca9-43ac-9d83-ca439e26aa77(a)s8g2000prg.googlegroups.com>, jeungster(a)gmail.com wrote: > 1.) I can write the function prototype like this: > > void doManipulation( const std::string & input, std::string & > output ); // (uses side-effect to return ouput string) > > 2.) Or, I can write the function prototype like this: > > std::string doManipulation( const std::string & input ); // (returns > the output string directly) But how do you make the two functions do equivalent things? Their semantics differ in subtle ways. In general, to make (1) equivalent to (2), it would have to be written like (this is pseudocode to show the issues): void doManipulation(const std::string& input, std::string& output) { try { // Are input and output the same string object? if (&input == &output) // do something magical if (WAYTOOBIG <= output.capacity()) // time for another trick // do the work } catch (...) { // perform more magic throw; } } Compared with the much simpler but sometimes more expensive: std::string doManipulation(const std::string& input) { // do the work } SInce it is easier to take correct code and make it faster when necessary than to take faster but subtly buggy code and make it correct, I usually use (2) unless I know (and can back up by measurement) that I can't afford it. -- Nevin ":-)" Liber <mailto:nevin(a)eviloverlord.com> 773 961-1620 [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Alberto Ganesh Barbati on 29 Mar 2008 23:45
Min-Yu Yang ha scritto: > "Niels Dekker - no return address" <noreply(a)this.is.invalid> wrote in > message news:47ebc3fb$0$14342$e4fe514c(a)news.xs4all.nl... >> Michael (jeungster) wrote: >>> >>> std::string doManipulation( const std::string & input ); >> >> Even if the compiler doesn't do RVO, the caller can still avoid the extra >> copying by binding the result to a const reference: >> >> const std::string & constFoo = doManipulation("bar"); > > What's the lifetime of the temporary std:string object returned by > doManipulation? Does the standard guarantee that constFoo still > references a > valid object after this statement? Yes, the standard guarantees that the lifetime of the temporary is extended to match that of the reference (�12.2/5). > Even if the standard guarantees that, the above code is risky because some > unknowing programmer may return that constFoo to a outer scope, which will > have undefined behavior because the temp string for sure will have been > destroyed. If the function returns by-reference you have undefined behaviour even if constFoo is not declared as a reference. It would be bad programming style in any case. If the functions returns by-value, the temporary is copied as part of the return statement before being destroyed, therefore there is no risk of undefined behaviour, whether constFoo is declared as a reference or not. HTH, Ganesh -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |