Topic: pre return optimization
Author: "terminator(jam)" <farid.mehrabi@gmail.com>
Date: Mon, 15 Oct 2007 09:52:49 CST Raw View
On Oct 14, 10:00 pm, Erik-wikst...@telia.com (Erik Wikstr m) wrote:
> On 2007-10-14 21:19, terminator wrote:
>
>
>
>
>
> > On Oct 14, 11:08 am, Greg Herlihy <gre...@pacbell.net> wrote:
> >> On Oct 9, 8:56 am, "terminator(jam)" <farid.mehr...@gmail.com> wrote:
>
> >> > consider:
>
> >> > struct memory_pig{//a really large type:
>
> >> > memory_pig(){
> >> > std::cout<<"mem pig default\n";
> >> > //etc...
> >> > };
>
> >> > memory_pig(memory_pig const&){
> >> > std::cout<<"mem pig copy\n";
> >> > //etc...
> >> > };
>
> >> > ~memory_pig(){
> >> > std::cout<<"mem pig finish\n";
> >> > //etc...
> >> > };
>
> >> > //etc...
>
> >> > };///struct memory_pig
>
> >> > memory_pig foo(){
> >> > memory_pig result;
> >> > result=something;
> >> > //etc...
> >> > result=something_else;
> >> > return result;
>
> >> > };
>
> >> > any time 'foo' is called the output will contain the following
> >> > sequence:
>
> >> > mem pig default
> >> > mem pig copy
> >> > mem pig finish
>
> >> > the last line of output may repeat based on how the result is
> >> > stored(rvo) or not.
> >> > So,two objects of a large type will be constructed and at least one is
> >> > destructed on every call to 'foo'
>
> >> The C++ Standard already allows the "(Named) Return Value
> >> Optimization" (NRVO or RVO for short). The optimization allows (under
> >> certain conditions) the compiler to construct the result of a function
> >> call "in place" - that is, directly in the object initialized with the
> >> function call result.
>
> >> So, to take advantage of this optimization, a program should use the
> >> result of a function call to initialize an object, instead of
> >> assigning the function result to an existing object.
>
> >> For example:
>
> >> #include <iostream>
>
> >> using std::cout;
>
> >> struct memory_pig
> >> { // a really large type:
> >> memory_pig()
> >> {
> >> cout << "mem pig default\n";
> >> }
> >> memory_pig(memory_pig const&)
> >> {
> >> cout << "mem pig copy\n";
> >> }
> >> ~memory_pig()
> >> {
> >> cout << "mem pig finish\n";
> >> }
> >> };
>
> >> memory_pig foo()
> >> {
> >> memory_pig result;
> >> // ...
> >> return result;
> >> }
>
> >> int main()
> >> {
> >> memory_pig m1 = foo();
> >> memory_pig m2 = foo();
> >> memory_pig m3 = foo();
> >> }
>
> >> I compiled the above program twice, once with and once without NRVO.
> >> The output of both programs is shown in the two columns below. As this
> >> comparison shows, NRVO can be a particular effective optimization -
> >> even for a small C++ program like the one used in this example.
>
> > I knew about RVO but not NRVO(that is what I am talking about).Is NRVO
> > standard behavoir or unspecified?
> > At least my compiler does not perform the NRVO.
>
> The standard allows this optimisation, but it does not require it (see
> section 12.8 paragraph 15). I think that most newer compilers support
> it, but you might have to turn up the optimisation level a bit.
>
> One important thing to remember is that when NRVO is in use the
> destructor will not be called for the local object, nor will the copy-
> constructor for the non-local object (m1 to m3 in the code above) be
> called. Thus you should not depend on any side effects that the copy-
> constructor or destructor might have.
>
prior to return and after return are two different case to me:I mean
before return even move should be disabled ,while after the return
either of move/copy must perform .
regards,
FM.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: =?UTF-8?B?RXJpayBXaWtzdHLDtm0=?= <Erik-wikstrom@telia.com>
Date: Mon, 15 Oct 2007 11:35:18 CST Raw View
===================================== MODERATOR'S COMMENT:
Please trim unnecessary material when replying.
===================================== END OF MODERATOR'S COMMENT
On 2007-10-15 17:52, terminator(jam) wrote:
> On Oct 14, 10:00 pm, Erik-wikst...@telia.com (Erik Wikstr m) wrote:
>> On 2007-10-14 21:19, terminator wrote:
>>
>>
>>
>>
>>
>> > On Oct 14, 11:08 am, Greg Herlihy <gre...@pacbell.net> wrote:
>> >> On Oct 9, 8:56 am, "terminator(jam)" <farid.mehr...@gmail.com> wrote:
>>
>> >> > consider:
>>
>> >> > struct memory_pig{//a really large type:
>>
>> >> > memory_pig(){
>> >> > std::cout<<"mem pig default\n";
>> >> > //etc...
>> >> > };
>>
>> >> > memory_pig(memory_pig const&){
>> >> > std::cout<<"mem pig copy\n";
>> >> > //etc...
>> >> > };
>>
>> >> > ~memory_pig(){
>> >> > std::cout<<"mem pig finish\n";
>> >> > //etc...
>> >> > };
>>
>> >> > //etc...
>>
>> >> > };///struct memory_pig
>>
>> >> > memory_pig foo(){
>> >> > memory_pig result;
>> >> > result=something;
>> >> > //etc...
>> >> > result=something_else;
>> >> > return result;
>>
>> >> > };
>>
>> >> > any time 'foo' is called the output will contain the following
>> >> > sequence:
>>
>> >> > mem pig default
>> >> > mem pig copy
>> >> > mem pig finish
>>
>> >> > the last line of output may repeat based on how the result is
>> >> > stored(rvo) or not.
>> >> > So,two objects of a large type will be constructed and at least one is
>> >> > destructed on every call to 'foo'
>>
>> >> The C++ Standard already allows the "(Named) Return Value
>> >> Optimization" (NRVO or RVO for short). The optimization allows (under
>> >> certain conditions) the compiler to construct the result of a function
>> >> call "in place" - that is, directly in the object initialized with the
>> >> function call result.
>>
>> >> So, to take advantage of this optimization, a program should use the
>> >> result of a function call to initialize an object, instead of
>> >> assigning the function result to an existing object.
>>
>> >> For example:
>>
>> >> #include <iostream>
>>
>> >> using std::cout;
>>
>> >> struct memory_pig
>> >> { // a really large type:
>> >> memory_pig()
>> >> {
>> >> cout << "mem pig default\n";
>> >> }
>> >> memory_pig(memory_pig const&)
>> >> {
>> >> cout << "mem pig copy\n";
>> >> }
>> >> ~memory_pig()
>> >> {
>> >> cout << "mem pig finish\n";
>> >> }
>> >> };
>>
>> >> memory_pig foo()
>> >> {
>> >> memory_pig result;
>> >> // ...
>> >> return result;
>> >> }
>>
>> >> int main()
>> >> {
>> >> memory_pig m1 = foo();
>> >> memory_pig m2 = foo();
>> >> memory_pig m3 = foo();
>> >> }
>>
>> >> I compiled the above program twice, once with and once without NRVO.
>> >> The output of both programs is shown in the two columns below. As this
>> >> comparison shows, NRVO can be a particular effective optimization -
>> >> even for a small C++ program like the one used in this example.
>>
>> > I knew about RVO but not NRVO(that is what I am talking about).Is NRVO
>> > standard behavoir or unspecified?
>> > At least my compiler does not perform the NRVO.
>>
>> The standard allows this optimisation, but it does not require it (see
>> section 12.8 paragraph 15). I think that most newer compilers support
>> it, but you might have to turn up the optimisation level a bit.
>>
>> One important thing to remember is that when NRVO is in use the
>> destructor will not be called for the local object, nor will the copy-
>> constructor for the non-local object (m1 to m3 in the code above) be
>> called. Thus you should not depend on any side effects that the copy-
>> constructor or destructor might have.
>>
>
> prior to return and after return are two different case to me:I mean
> before return even move should be disabled ,while after the return
> either of move/copy must perform .
Sorry, but you lost me there, what move? Of what to where?
--
Erik Wikstr m
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: int19h@gmail.com
Date: Mon, 15 Oct 2007 23:44:30 CST Raw View
On Oct 9, 7:56 pm, "terminator(jam)" <farid.mehr...@gmail.com> wrote:
> consider:
>
> struct memory_pig{//a really large type:
>
> memory_pig(){
> std::cout<<"mem pig default\n";
> //etc...
> };
>
> memory_pig(memory_pig const&){
> std::cout<<"mem pig copy\n";
> //etc...
> };
>
> ~memory_pig(){
> std::cout<<"mem pig finish\n";
> //etc...
> };
>
> //etc...
>
> };///struct memory_pig
>
> memory_pig foo(){
> memory_pig result;
> result=something;
> //etc...
> result=something_else;
> return result;
>
> };
>
> any time 'foo' is called the output will contain the following
> sequence:
>
> mem pig default
> mem pig copy
> mem pig finish
It won't. It certainly won't do that with the example given, since
there's no clear association in it between the copy constructor and
the assignment operator (considering that the latter isn't even
defined). Assuming there was such an association, though, I'd rather
expect to see:
mem pig default
mem pig copy // first assignment
mem pig copy // second assignment
mem pig finish
Which is correct and fine - if you have explicitly written the
assignment operator twice, then surely you want the associated side-
effects? And if you do not, then perhaps you shouldn't have written it
that way.
> that is you can refrence the returned object inside the function and
> decrease the overhead for copying large objects.C++ lacks such syntax
> and IMHO we should be able to mark the result object as referencing
> the actual return so that there is no need for the extra copy
> construction
This is precisely what NRVO does.
I have a feeling that you're confusing assignment with initialization
in this case. Assignment operator always applies to an already-
initialized object - the compiler cannot elide the initialization
except for the trivial cases (e.g. POD types), which is why operator=
still results in unnecessary copying even when the compiler implements
NRVO. It's not a problem with NRVO though - it's because assignment is
used where just initialization would suffice. Direct initialization is
still more efficient then assignment-following-initialization, even
with the move semantics of C++0x.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "terminator(jam)" <farid.mehrabi@gmail.com>
Date: Tue, 16 Oct 2007 11:55:54 CST Raw View
On Oct 15, 8:35 pm, Erik Wikstr m <Erik-wikst...@telia.com> wrote:
> ===================================== MODERATOR'S COMMENT:
>
> Please trim unnecessary material when replying.
>
> ===================================== END OF MODERATOR'S COMMENT
> On 2007-10-15 17:52, terminator(jam) wrote:
>
>
>
>
>
> > On Oct 14, 10:00 pm, Erik-wikst...@telia.com (Erik Wikstr m) wrote:
> >> On 2007-10-14 21:19, terminator wrote:
>
> >> > On Oct 14, 11:08 am, Greg Herlihy <gre...@pacbell.net> wrote:
> >> >> On Oct 9, 8:56 am, "terminator(jam)" <farid.mehr...@gmail.com> wrote:
>
> >> >> > consider:
>
> >> >> > struct memory_pig{//a really large type:
>
> >> >> > memory_pig(){
> >> >> > std::cout<<"mem pig default\n";
> >> >> > //etc...
> >> >> > };
>
> >> >> > memory_pig(memory_pig const&){
> >> >> > std::cout<<"mem pig copy\n";
> >> >> > //etc...
> >> >> > };
>
> >> >> > ~memory_pig(){
> >> >> > std::cout<<"mem pig finish\n";
> >> >> > //etc...
> >> >> > };
>
> >> >> > //etc...
>
> >> >> > };///struct memory_pig
>
> >> >> > memory_pig foo(){
> >> >> > memory_pig result;
> >> >> > result=something;
> >> >> > //etc...
> >> >> > result=something_else;
> >> >> > return result;
>
> >> >> > };
>
> >> >> > any time 'foo' is called the output will contain the following
> >> >> > sequence:
>
> >> >> > mem pig default
> >> >> > mem pig copy
> >> >> > mem pig finish
>
> >> >> > the last line of output may repeat based on how the result is
> >> >> > stored(rvo) or not.
> >> >> > So,two objects of a large type will be constructed and at least one is
> >> >> > destructed on every call to 'foo'
>
> >> >> The C++ Standard already allows the "(Named) Return Value
> >> >> Optimization" (NRVO or RVO for short). The optimization allows (under
> >> >> certain conditions) the compiler to construct the result of a function
> >> >> call "in place" - that is, directly in the object initialized with the
> >> >> function call result.
>
> >> >> So, to take advantage of this optimization, a program should use the
> >> >> result of a function call to initialize an object, instead of
> >> >> assigning the function result to an existing object.
>
> >> >> For example:
>
> >> >> #include <iostream>
>
> >> >> using std::cout;
>
> >> >> struct memory_pig
> >> >> { // a really large type:
> >> >> memory_pig()
> >> >> {
> >> >> cout << "mem pig default\n";
> >> >> }
> >> >> memory_pig(memory_pig const&)
> >> >> {
> >> >> cout << "mem pig copy\n";
> >> >> }
> >> >> ~memory_pig()
> >> >> {
> >> >> cout << "mem pig finish\n";
> >> >> }
> >> >> };
>
> >> >> memory_pig foo()
> >> >> {
> >> >> memory_pig result;
> >> >> // ...
> >> >> return result;
> >> >> }
>
> >> >> int main()
> >> >> {
> >> >> memory_pig m1 = foo();
> >> >> memory_pig m2 = foo();
> >> >> memory_pig m3 = foo();
> >> >> }
>
> >> >> I compiled the above program twice, once with and once without NRVO.
> >> >> The output of both programs is shown in the two columns below. As this
> >> >> comparison shows, NRVO can be a particular effective optimization -
> >> >> even for a small C++ program like the one used in this example.
>
> >> > I knew about RVO but not NRVO(that is what I am talking about).Is NRVO
> >> > standard behavoir or unspecified?
> >> > At least my compiler does not perform the NRVO.
>
> >> The standard allows this optimisation, but it does not require it (see
> >> section 12.8 paragraph 15). I think that most newer compilers support
> >> it, but you might have to turn up the optimisation level a bit.
>
> >> One important thing to remember is that when NRVO is in use the
> >> destructor will not be called for the local object, nor will the copy-
> >> constructor for the non-local object (m1 to m3 in the code above) be
> >> called. Thus you should not depend on any side effects that the copy-
> >> constructor or destructor might have.
>
> > prior to return and after return are two different case to me:I mean
> > before return even move should be disabled ,while after the return
> > either of move/copy must perform .
>
> Sorry, but you lost me there, what move? Of what to where?
>
Move ctor of course.
regards,
FM.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "terminator(jam)" <farid.mehrabi@gmail.com>
Date: Tue, 16 Oct 2007 13:26:48 CST Raw View
On Oct 16, 8:44 am, int...@gmail.com wrote:
> On Oct 9, 7:56 pm, "terminator(jam)" <farid.mehr...@gmail.com> wrote:
>
>
>
>
>
> > consider:
>
> > struct memory_pig{//a really large type:
>
> > memory_pig(){
> > std::cout<<"mem pig default\n";
> > //etc...
> > };
>
> > memory_pig(memory_pig const&){
> > std::cout<<"mem pig copy\n";
> > //etc...
> > };
>
> > ~memory_pig(){
> > std::cout<<"mem pig finish\n";
> > //etc...
> > };
>
> > //etc...
>
> > };///struct memory_pig
>
> > memory_pig foo(){
> > memory_pig result;
> > result=something;
> > //etc...
> > result=something_else;
> > return result;
>
> > };
>
> > any time 'foo' is called the output will contain the following
> > sequence:
>
> > mem pig default
> > mem pig copy
> > mem pig finish
>
> It won't. It certainly won't do that with the example given, since
> there's no clear association in it between the copy constructor and
> the assignment operator (considering that the latter isn't even
> defined). Assuming there was such an association, though, I'd rather
> expect to see:
>
> mem pig default
> mem pig copy // first assignment
> mem pig copy // second assignment
> mem pig finish
>
As I wrote before its just an illustration and I did not mean any
assignment,replace it with any function( eg. modify(result) ;).
> Which is correct and fine - if you have explicitly written the
> assignment operator twice, then surely you want the associated side-
> effects? And if you do not, then perhaps you shouldn't have written it
> that way.
>
> > that is you can refrence the returned object inside the function and
> > decrease the overhead for copying large objects.C++ lacks such syntax
> > and IMHO we should be able to mark the result object as referencing
> > the actual return so that there is no need for the extra copy
> > construction
>
> This is precisely what NRVO does.
>
I was certain about the NRVO by the time I started the post.However
NRVO is a compiler option(ugly!!!) not a demand .With NRVO we have two
distinct phases optimize simultaniously : prior to return inside the
callee and after that inside the caller:
A foo(){
A ret;//this will be return under any conditions.
//....
return ret;//pre return :no copy/move
};
class A a=foo();//after return : copy/move to a
> I have a feeling that you're confusing assignment with initialization
> in this case. Assignment operator always applies to an already-
> initialized object - the compiler cannot elide the initialization
> except for the trivial cases (e.g. POD types), which is why operator=
> still results in unnecessary copying even when the compiler implements
> NRVO. It's not a problem with NRVO though - it's because assignment is
> used where just initialization would suffice. Direct initialization is
> still more efficient then assignment-following-initialization, even
> with the move semantics of C++0x.
Everybody makes mistakes while learning , but confusing assignment
with copy certainly has never been the mistake I can make.
regards,
FM
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Erik-wikstrom@telia.com (=?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=)
Date: Tue, 16 Oct 2007 18:37:25 GMT Raw View
On 2007-10-16 19:55, terminator(jam) wrote:
> On Oct 15, 8:35 pm, Erik Wikstr=C3=B6m <Erik-wikst...@telia.com> wrote:
>> On 2007-10-15 17:52, terminator(jam) wrote:
>> > On Oct 14, 10:00 pm, Erik-wikst...@telia.com (Erik Wikstr=C3=B6m) wr=
ote:
>> >> On 2007-10-14 21:19, terminator wrote:
>>
>> >> > On Oct 14, 11:08 am, Greg Herlihy <gre...@pacbell.net> wrote:
>> >> >> On Oct 9, 8:56 am, "terminator(jam)" <farid.mehr...@gmail.com> w=
rote:
>> >> >> The C++ Standard already allows the "(Named) Return Value
>> >> >> Optimization" (NRVO or RVO for short). The optimization allows (=
under
>> >> >> certain conditions) the compiler to construct the result of a fu=
nction
>> >> >> call "in place" - that is, directly in the object initialized wi=
th the
>> >> >> function call result.
>>
>> >> >> So, to take advantage of this optimization, a program should use=
the
>> >> >> result of a function call to initialize an object, instead of
>> >> >> assigning the function result to an existing object.
>>
>> >> >> For example:
>>
>> >> >> #include <iostream>
>>
>> >> >> using std::cout;
>>
>> >> >> struct memory_pig
>> >> >> { // a really large type:
>> >> >> memory_pig()
>> >> >> {
>> >> >> cout << "mem pig default\n";
>> >> >> }
>> >> >> memory_pig(memory_pig const&)
>> >> >> {
>> >> >> cout << "mem pig copy\n";
>> >> >> }
>> >> >> ~memory_pig()
>> >> >> {
>> >> >> cout << "mem pig finish\n";
>> >> >> }
>> >> >> };
>>
>> >> >> memory_pig foo()
>> >> >> {
>> >> >> memory_pig result;
>> >> >> // ...
>> >> >> return result;
>> >> >> }
>>
>> >> >> int main()
>> >> >> {
>> >> >> memory_pig m1 =3D foo();
>> >> >> memory_pig m2 =3D foo();
>> >> >> memory_pig m3 =3D foo();
>> >> >> }
>>
>> >> >> I compiled the above program twice, once with and once without N=
RVO.
>> >> >> The output of both programs is shown in the two columns below. A=
s this
>> >> >> comparison shows, NRVO can be a particular effective optimizatio=
n -
>> >> >> even for a small C++ program like the one used in this example.
>>
>> >> > I knew about RVO but not NRVO(that is what I am talking about).Is=
NRVO
>> >> > standard behavoir or unspecified?
>> >> > At least my compiler does not perform the NRVO.
>>
>> >> The standard allows this optimisation, but it does not require it (=
see
>> >> section 12.8 paragraph 15). I think that most newer compilers suppo=
rt
>> >> it, but you might have to turn up the optimisation level a bit.
>>
>> >> One important thing to remember is that when NRVO is in use the
>> >> destructor will not be called for the local object, nor will the co=
py-
>> >> constructor for the non-local object (m1 to m3 in the code above) b=
e
>> >> called. Thus you should not depend on any side effects that the cop=
y-
>> >> constructor or destructor might have.
>>
>> > prior to return and after return are two different case to me:I mean
>> > before return even move should be disabled ,while after the return
>> > either of move/copy must perform .
>>
>> Sorry, but you lost me there, what move? Of what to where?
>>
>=20
> Move ctor of course.
Sorry, but I still do not understand. What do you mean with RNVO should
be disabled before return but not after? It is something that is
performed *during* return.
--=20
Erik Wikstr=C3=B6m
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "terminator(jam)" <farid.mehrabi@gmail.com>
Date: Wed, 17 Oct 2007 09:53:24 CST Raw View
On Oct 16, 9:37 pm, Erik-wikst...@telia.com (Erik Wikstr m) wrote:
> On 2007-10-16 19:55, terminator(jam) wrote:
>
>
>
>
>
> > On Oct 15, 8:35 pm, Erik Wikstr m <Erik-wikst...@telia.com> wrote:
> >> On 2007-10-15 17:52, terminator(jam) wrote:
> >> > On Oct 14, 10:00 pm, Erik-wikst...@telia.com (Erik Wikstr m) wrote:
> >> >> On 2007-10-14 21:19, terminator wrote:
>
> >> >> > On Oct 14, 11:08 am, Greg Herlihy <gre...@pacbell.net> wrote:
> >> >> >> On Oct 9, 8:56 am, "terminator(jam)" <farid.mehr...@gmail.com> wrote:
> >> >> >> The C++ Standard already allows the "(Named) Return Value
> >> >> >> Optimization" (NRVO or RVO for short). The optimization allows (under
> >> >> >> certain conditions) the compiler to construct the result of a function
> >> >> >> call "in place" - that is, directly in the object initialized with the
> >> >> >> function call result.
>
> >> >> >> So, to take advantage of this optimization, a program should use the
> >> >> >> result of a function call to initialize an object, instead of
> >> >> >> assigning the function result to an existing object.
>
> >> >> >> For example:
>
> >> >> >> #include <iostream>
>
> >> >> >> using std::cout;
>
> >> >> >> struct memory_pig
> >> >> >> { // a really large type:
> >> >> >> memory_pig()
> >> >> >> {
> >> >> >> cout << "mem pig default\n";
> >> >> >> }
> >> >> >> memory_pig(memory_pig const&)
> >> >> >> {
> >> >> >> cout << "mem pig copy\n";
> >> >> >> }
> >> >> >> ~memory_pig()
> >> >> >> {
> >> >> >> cout << "mem pig finish\n";
> >> >> >> }
> >> >> >> };
>
> >> >> >> memory_pig foo()
> >> >> >> {
> >> >> >> memory_pig result;
> >> >> >> // ...
> >> >> >> return result;
> >> >> >> }
>
> >> >> >> int main()
> >> >> >> {
> >> >> >> memory_pig m1 = foo();
> >> >> >> memory_pig m2 = foo();
> >> >> >> memory_pig m3 = foo();
> >> >> >> }
>
> >> >> >> I compiled the above program twice, once with and once without NRVO.
> >> >> >> The output of both programs is shown in the two columns below. As this
> >> >> >> comparison shows, NRVO can be a particular effective optimization -
> >> >> >> even for a small C++ program like the one used in this example.
>
> >> >> > I knew about RVO but not NRVO(that is what I am talking about).Is NRVO
> >> >> > standard behavoir or unspecified?
> >> >> > At least my compiler does not perform the NRVO.
>
> >> >> The standard allows this optimisation, but it does not require it (see
> >> >> section 12.8 paragraph 15). I think that most newer compilers support
> >> >> it, but you might have to turn up the optimisation level a bit.
>
> >> >> One important thing to remember is that when NRVO is in use the
> >> >> destructor will not be called for the local object, nor will the copy-
> >> >> constructor for the non-local object (m1 to m3 in the code above) be
> >> >> called. Thus you should not depend on any side effects that the copy-
> >> >> constructor or destructor might have.
>
> >> > prior to return and after return are two different case to me:I mean
> >> > before return even move should be disabled ,while after the return
> >> > either of move/copy must perform .
>
> >> Sorry, but you lost me there, what move? Of what to where?
>
> > Move ctor of course.
>
> Sorry, but I still do not understand. What do you mean with RNVO should
> be disabled before return but not after? It is something that is
> performed *during* return.
I mean the whole concept of optimization(rvo,nrvo,etc). IMHO:
If a function always returns the same local object the returned object
must be the local object itself rather than a copy/move version of the
local.
If a function returns one of its parameter values returned object is
copy/moved from that parameter because a change in location of the
object is almost inevitable.
If an object is constructed with an rvalue it should be copy/moved.
regards,
FM
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: int19h@gmail.com
Date: Wed, 17 Oct 2007 11:53:54 CST Raw View
On 16 Oct, 23:26, "terminator(jam)" <farid.mehr...@gmail.com> wrote:
> A foo(){
> A ret;//this will be return under any conditions.
> //....
> return ret;//pre return :no copy/move};
>
> class A a=foo();//after return : copy/move to a
This is not the case. If the compiler correctly implements NRVO, the
example above will result in a single construction of A using the
default constructor, and then a subsequent destruction. No copies or
moves are made at any point.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Erik-wikstrom@telia.com (=?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=)
Date: Wed, 17 Oct 2007 17:13:28 GMT Raw View
On 2007-10-17 17:53, terminator(jam) wrote:
> On Oct 16, 9:37 pm, Erik-wikst...@telia.com (Erik Wikstr=C3=B6m) wrote:
>> On 2007-10-16 19:55, terminator(jam) wrote:
>> > On Oct 15, 8:35 pm, Erik Wikstr=C3=B6m <Erik-wikst...@telia.com> wro=
te:
>> >> On 2007-10-15 17:52, terminator(jam) wrote:
>> >> > On Oct 14, 10:00 pm, Erik-wikst...@telia.com (Erik Wikstr=C3=B6m)=
wrote:
>> >> >> On 2007-10-14 21:19, terminator wrote:
>>
>> >> >> > On Oct 14, 11:08 am, Greg Herlihy <gre...@pacbell.net> wrote:
>> >> >> >> On Oct 9, 8:56 am, "terminator(jam)" <farid.mehr...@gmail.com=
> wrote:
>> >> >> >> The C++ Standard already allows the "(Named) Return Value
>> >> >> >> Optimization" (NRVO or RVO for short). The optimization allow=
s (under
>> >> >> >> certain conditions) the compiler to construct the result of a=
function
>> >> >> >> call "in place" - that is, directly in the object initialized=
with the
>> >> >> >> function call result.
>>
>> >> >> >> So, to take advantage of this optimization, a program should =
use the
>> >> >> >> result of a function call to initialize an object, instead o=
f
>> >> >> >> assigning the function result to an existing object.
>>
>> >> >> >> For example:
>>
>> >> >> >> #include <iostream>
>>
>> >> >> >> using std::cout;
>>
>> >> >> >> struct memory_pig
>> >> >> >> { // a really large type:
>> >> >> >> memory_pig()
>> >> >> >> {
>> >> >> >> cout << "mem pig default\n";
>> >> >> >> }
>> >> >> >> memory_pig(memory_pig const&)
>> >> >> >> {
>> >> >> >> cout << "mem pig copy\n";
>> >> >> >> }
>> >> >> >> ~memory_pig()
>> >> >> >> {
>> >> >> >> cout << "mem pig finish\n";
>> >> >> >> }
>> >> >> >> };
>>
>> >> >> >> memory_pig foo()
>> >> >> >> {
>> >> >> >> memory_pig result;
>> >> >> >> // ...
>> >> >> >> return result;
>> >> >> >> }
>>
>> >> >> >> int main()
>> >> >> >> {
>> >> >> >> memory_pig m1 =3D foo();
>> >> >> >> memory_pig m2 =3D foo();
>> >> >> >> memory_pig m3 =3D foo();
>> >> >> >> }
>>
>> >> >> >> I compiled the above program twice, once with and once withou=
t NRVO.
>> >> >> >> The output of both programs is shown in the two columns below=
. As this
>> >> >> >> comparison shows, NRVO can be a particular effective optimiza=
tion -
>> >> >> >> even for a small C++ program like the one used in this exampl=
e.
>>
>> >> >> > I knew about RVO but not NRVO(that is what I am talking about)=
.Is NRVO
>> >> >> > standard behavoir or unspecified?
>> >> >> > At least my compiler does not perform the NRVO.
>>
>> >> >> The standard allows this optimisation, but it does not require i=
t (see
>> >> >> section 12.8 paragraph 15). I think that most newer compilers su=
pport
>> >> >> it, but you might have to turn up the optimisation level a bit.
>>
>> >> >> One important thing to remember is that when NRVO is in use the
>> >> >> destructor will not be called for the local object, nor will the=
copy-
>> >> >> constructor for the non-local object (m1 to m3 in the code above=
) be
>> >> >> called. Thus you should not depend on any side effects that the =
copy-
>> >> >> constructor or destructor might have.
>>
>> >> > prior to return and after return are two different case to me:I m=
ean
>> >> > before return even move should be disabled ,while after the retur=
n
>> >> > either of move/copy must perform .
>>
>> >> Sorry, but you lost me there, what move? Of what to where?
>>
>> > Move ctor of course.
>>
>> Sorry, but I still do not understand. What do you mean with RNVO shoul=
d
>> be disabled before return but not after? It is something that is
>> performed *during* return.
>=20
> I mean the whole concept of optimization(rvo,nrvo,etc). IMHO:
> If a function always returns the same local object the returned object
> must be the local object itself
You mean for a function such as
foo bar()
{
foo f;
return f;
}
NRVO should be used? That is (to my knowledge) the case if NRVO is
enabled in the compiler.
> rather than a copy/move version of the local.
What is the difference between copy and move? I would say that NRVO is
move, since the object created in the function is moved to the
"surrounding" context/scope instead of being used as the basis of a copy.
> If a function returns one of its parameter values returned object is
> copy/moved from that parameter because a change in location of the
> object is almost inevitable.
Assuming that you by copy/move mean that the object in the function is
being copied to the surrounding scope, did you mean that something like
foo bar(bool b)
{
foo f1, f2;
if (b)
return f1;
else
return f2;
}
should not use NRVO? Again, to my knowledge that is the case, since the
compiler can not predict which of the objects will be returned so a copy
is necessary.
> If an object is constructed with an rvalue it should be copy/moved.
You mean something similar to
foo bar()
{
foo f1, f2;
return f1 + f2;
}
In that case NRVO could be used depending on whether the compiler knows
which object will be returned or not. So the above could utilise NRVO
but something like
foo bar(bool b)
{
foo f1, f2, f3;
if (b)
return f1 + f2;
else
return f2 + f3;
}
could not.
If the above is not what you meant, then I am sorry to have failed to
understand you. Perhaps you could try to rephrase the question or use
simple code examples.
--=20
Erik Wikstr=C3=B6m
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Greg Herlihy <greghe@pacbell.net>
Date: Sun, 14 Oct 2007 02:08:09 CST Raw View
On Oct 9, 8:56 am, "terminator(jam)" <farid.mehr...@gmail.com> wrote:
> consider:
>
> struct memory_pig{//a really large type:
>
> memory_pig(){
> std::cout<<"mem pig default\n";
> //etc...
> };
>
> memory_pig(memory_pig const&){
> std::cout<<"mem pig copy\n";
> //etc...
> };
>
> ~memory_pig(){
> std::cout<<"mem pig finish\n";
> //etc...
> };
>
> //etc...
>
> };///struct memory_pig
>
> memory_pig foo(){
> memory_pig result;
> result=something;
> //etc...
> result=something_else;
> return result;
>
> };
>
> any time 'foo' is called the output will contain the following
> sequence:
>
> mem pig default
> mem pig copy
> mem pig finish
>
> the last line of output may repeat based on how the result is
> stored(rvo) or not.
> So,two objects of a large type will be constructed and at least one is
> destructed on every call to 'foo'
The C++ Standard already allows the "(Named) Return Value
Optimization" (NRVO or RVO for short). The optimization allows (under
certain conditions) the compiler to construct the result of a function
call "in place" - that is, directly in the object initialized with the
function call result.
So, to take advantage of this optimization, a program should use the
result of a function call to initialize an object, instead of
assigning the function result to an existing object.
For example:
#include <iostream>
using std::cout;
struct memory_pig
{ // a really large type:
memory_pig()
{
cout << "mem pig default\n";
}
memory_pig(memory_pig const&)
{
cout << "mem pig copy\n";
}
~memory_pig()
{
cout << "mem pig finish\n";
}
};
memory_pig foo()
{
memory_pig result;
// ...
return result;
}
int main()
{
memory_pig m1 = foo();
memory_pig m2 = foo();
memory_pig m3 = foo();
}
I compiled the above program twice, once with and once without NRVO.
The output of both programs is shown in the two columns below. As this
comparison shows, NRVO can be a particular effective optimization -
even for a small C++ program like the one used in this example.
Program Output
Without NRVO: With NRVO:
mem pig default mem pig default
mem pig copy mem pig default
mem pig finish mem pig default
mem pig copy mem pig finish
mem pig finish mem pig finish
mem pig default mem pig finish
mem pig copy
mem pig finish
mem pig copy
mem pig finish
mem pig default
mem pig copy
mem pig finish
mem pig copy
mem pig finish
mem pig finish
mem pig finish
mem pig finish
Greg
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: terminator <farid.mehrabi@gmail.com>
Date: Sun, 14 Oct 2007 13:19:28 CST Raw View
On Oct 14, 11:08 am, Greg Herlihy <gre...@pacbell.net> wrote:
> On Oct 9, 8:56 am, "terminator(jam)" <farid.mehr...@gmail.com> wrote:
>
>
>
>
>
> > consider:
>
> > struct memory_pig{//a really large type:
>
> > memory_pig(){
> > std::cout<<"mem pig default\n";
> > //etc...
> > };
>
> > memory_pig(memory_pig const&){
> > std::cout<<"mem pig copy\n";
> > //etc...
> > };
>
> > ~memory_pig(){
> > std::cout<<"mem pig finish\n";
> > //etc...
> > };
>
> > //etc...
>
> > };///struct memory_pig
>
> > memory_pig foo(){
> > memory_pig result;
> > result=something;
> > //etc...
> > result=something_else;
> > return result;
>
> > };
>
> > any time 'foo' is called the output will contain the following
> > sequence:
>
> > mem pig default
> > mem pig copy
> > mem pig finish
>
> > the last line of output may repeat based on how the result is
> > stored(rvo) or not.
> > So,two objects of a large type will be constructed and at least one is
> > destructed on every call to 'foo'
>
> The C++ Standard already allows the "(Named) Return Value
> Optimization" (NRVO or RVO for short). The optimization allows (under
> certain conditions) the compiler to construct the result of a function
> call "in place" - that is, directly in the object initialized with the
> function call result.
>
> So, to take advantage of this optimization, a program should use the
> result of a function call to initialize an object, instead of
> assigning the function result to an existing object.
>
> For example:
>
> #include <iostream>
>
> using std::cout;
>
> struct memory_pig
> { // a really large type:
> memory_pig()
> {
> cout << "mem pig default\n";
> }
> memory_pig(memory_pig const&)
> {
> cout << "mem pig copy\n";
> }
> ~memory_pig()
> {
> cout << "mem pig finish\n";
> }
> };
>
> memory_pig foo()
> {
> memory_pig result;
> // ...
> return result;
> }
>
> int main()
> {
> memory_pig m1 = foo();
> memory_pig m2 = foo();
> memory_pig m3 = foo();
> }
>
> I compiled the above program twice, once with and once without NRVO.
> The output of both programs is shown in the two columns below. As this
> comparison shows, NRVO can be a particular effective optimization -
> even for a small C++ program like the one used in this example.
>
> Program Output
>
> Without NRVO: With NRVO:
>
> mem pig default mem pig default
> mem pig copy mem pig default
> mem pig finish mem pig default
> mem pig copy mem pig finish
> mem pig finish mem pig finish
> mem pig default mem pig finish
> mem pig copy
> mem pig finish
> mem pig copy
> mem pig finish
> mem pig default
> mem pig copy
> mem pig finish
> mem pig copy
> mem pig finish
> mem pig finish
> mem pig finish
> mem pig finish
>
I knew about RVO but not NRVO(that is what I am talking about).Is NRVO
standard behavoir or unspecified?
At least my compiler does not perform the NRVO.
thanx,
FM.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Erik-wikstrom@telia.com (=?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=)
Date: Sun, 14 Oct 2007 19:00:39 GMT Raw View
On 2007-10-14 21:19, terminator wrote:
> On Oct 14, 11:08 am, Greg Herlihy <gre...@pacbell.net> wrote:
>> On Oct 9, 8:56 am, "terminator(jam)" <farid.mehr...@gmail.com> wrote:
>>
>>
>>
>>
>>
>> > consider:
>>
>> > struct memory_pig{//a really large type:
>>
>> > memory_pig(){
>> > std::cout<<"mem pig default\n";
>> > //etc...
>> > };
>>
>> > memory_pig(memory_pig const&){
>> > std::cout<<"mem pig copy\n";
>> > //etc...
>> > };
>>
>> > ~memory_pig(){
>> > std::cout<<"mem pig finish\n";
>> > //etc...
>> > };
>>
>> > //etc...
>>
>> > };///struct memory_pig
>>
>> > memory_pig foo(){
>> > memory_pig result;
>> > result=3Dsomething;
>> > //etc...
>> > result=3Dsomething_else;
>> > return result;
>>
>> > };
>>
>> > any time 'foo' is called the output will contain the following
>> > sequence:
>>
>> > mem pig default
>> > mem pig copy
>> > mem pig finish
>>
>> > the last line of output may repeat based on how the result is
>> > stored(rvo) or not.
>> > So,two objects of a large type will be constructed and at least one =
is
>> > destructed on every call to 'foo'
>>
>> The C++ Standard already allows the "(Named) Return Value
>> Optimization" (NRVO or RVO for short). The optimization allows (under
>> certain conditions) the compiler to construct the result of a function
>> call "in place" - that is, directly in the object initialized with the
>> function call result.
>>
>> So, to take advantage of this optimization, a program should use the
>> result of a function call to initialize an object, instead of
>> assigning the function result to an existing object.
>>
>> For example:
>>
>> #include <iostream>
>>
>> using std::cout;
>>
>> struct memory_pig
>> { // a really large type:
>> memory_pig()
>> {
>> cout << "mem pig default\n";
>> }
>> memory_pig(memory_pig const&)
>> {
>> cout << "mem pig copy\n";
>> }
>> ~memory_pig()
>> {
>> cout << "mem pig finish\n";
>> }
>> };
>>
>> memory_pig foo()
>> {
>> memory_pig result;
>> // ...
>> return result;
>> }
>>
>> int main()
>> {
>> memory_pig m1 =3D foo();
>> memory_pig m2 =3D foo();
>> memory_pig m3 =3D foo();
>> }
>>
>> I compiled the above program twice, once with and once without NRVO.
>> The output of both programs is shown in the two columns below. As this
>> comparison shows, NRVO can be a particular effective optimization -
>> even for a small C++ program like the one used in this example.
>>
> I knew about RVO but not NRVO(that is what I am talking about).Is NRVO
> standard behavoir or unspecified?
> At least my compiler does not perform the NRVO.
The standard allows this optimisation, but it does not require it (see
section 12.8 paragraph 15). I think that most newer compilers support
it, but you might have to turn up the optimisation level a bit.
One important thing to remember is that when NRVO is in use the
destructor will not be called for the local object, nor will the copy-
constructor for the non-local object (m1 to m3 in the code above) be
called. Thus you should not depend on any side effects that the copy-
constructor or destructor might have.
--=20
Erik Wikstr=C3=B6m
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "terminator(jam)" <farid.mehrabi@gmail.com>
Date: Tue, 9 Oct 2007 09:56:13 CST Raw View
consider:
struct memory_pig{//a really large type:
memory_pig(){
std::cout<<"mem pig default\n";
//etc...
};
memory_pig(memory_pig const&){
std::cout<<"mem pig copy\n";
//etc...
};
~memory_pig(){
std::cout<<"mem pig finish\n";
//etc...
};
//etc...
};///struct memory_pig
memory_pig foo(){
memory_pig result;
result=something;
//etc...
result=something_else;
return result;
};
any time 'foo' is called the output will contain the following
sequence:
mem pig default
mem pig copy
mem pig finish
the last line of output may repeat based on how the result is
stored(rvo) or not.
So,two objects of a large type will be constructed and at least one is
destructed on every call to 'foo' in PASCAL you can write:
function foo:memory_pig
begin
foo:=something;
{etc...}
foo:=somthing_else;
end
that is you can refrence the returned object inside the function and
decrease the overhead for copying large objects.C++ lacks such syntax
and IMHO we should be able to mark the result object as referencing
the actual return so that there is no need for the extra copy
construction;this is espesifically beneficall when dealing with
operator definitions .We can declare the return itself as an object.I
suggest the following syntax:
class ret_type funxn (paramlist){
ret_type return /*optional:*/(initiallizer params);
//etc...
if(false)return;//return like void functions
//return something;//error:named return accepts no param.
return=something;//ok;
return=something_else;
return.member_funxn();
another_funcxn(return);
};
Provided that 'return' is declared as an object { whenever you use the
'return' keyword inside pharantesis or accompanied via an operator ?
the return object is referenced :otherwise a parameterless 'return'
returns to the caller.
The return object is an lvalue inside the function and can be aliased
for readability:
memory_pig foo(){
memory_pig return , & result=return;
result=something;
//etc...
result=something_else;
};
and whenever 'foo' is called the output looks like this:
mem pig default
the unnessesary copy/move has vanished and the destruction of
temporary depends on what you do with it.
regards,
FM.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]