Re: [eigen] Very interesting read which might be important for us

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]


DOH! I could've saved a lot of typing if I'd just read the comments. That commenter and I came up with much the same code and it surprised us in much the same way.

Hauke Heibel wrote:
Yeah, this is also mentioned in one of the comments of the article.
The comment starts with

"That’s not the Guru question, the guru question what is the exception
to this rule?"

- Hauke

On Wed, May 19, 2010 at 4:34 PM, Mark Borgerding <mark@xxxxxxxxxxxxxx> wrote:
Hauke Heibel wrote:
Well, at least from a programmers point of view.


http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/

- Hauke


Interesting.  Unfortunately this const-reference-to-a-temporary seems to be
limited to immediate stack variables, not stack structures that have
const-refs inside them.
I hoped this might allow one to create a lightweight reference that could be
passed around.  See attached file.
The tests 3&4 did not behave as I expected.  I think what I was hoping for
is not possible with automatic variables.   The output from the program
(linux x86_64, gcc 4.1.2) is:

[markb@hedy ~]$ g++ -Wall -O2 -o test_const_retval test_const_retval.cc &&
./test_const_retval

test 1: return by value:
BigExpensiveObject default constructor
BigExpensiveObject being used
BigExpensiveObject destructor

test 2:grab const ref to a temporary
BigExpensiveObject default constructor
BigExpensiveObject being used
BigExpensiveObject destructor

test 3:proxy object created from function returning temporary
BigExpensiveObject default constructor
ConstRef constructor
BigExpensiveObject destructor
BigExpensiveObject being used
ConstRef destructor

test 4:proxy object
BigExpensiveObject default constructor
ConstRef constructor
BigExpensiveObject destructor
BigExpensiveObject being used
ConstRef destructor


#include <iostream>
using namespace std;

struct BigExpensiveObject
{
   BigExpensiveObject(){ cout << "BigExpensiveObject default constructor\n";
}
   ~BigExpensiveObject() { cout << "BigExpensiveObject destructor\n"; }
   BigExpensiveObject(const BigExpensiveObject & other ){ cout <<
"BigExpensiveObject copy constructor\n"; }
   void Use() const { cout << "BigExpensiveObject being used\n"; }
};

struct ConstRef
{
   const BigExpensiveObject &  ref;
   ConstRef( const BigExpensiveObject & beo) : ref(beo) {cout << "ConstRef
constructor\n";}
   ConstRef( const ConstRef & other) : ref(other.ref) {cout << "ConstRef
copy constructor\n";}
   ~ConstRef() {cout << "ConstRef destructor\n";}
   operator const BigExpensiveObject &  () const {return ref;}
};

BigExpensiveObject simple_return_value()
{
   BigExpensiveObject beo;
   return beo;
}

ConstRef proxy_return_value()
{
   BigExpensiveObject beo;
   return ConstRef(beo);
}

int main(int argc,char ** argv)
{
   cout <<  "\ntest 1: return by value:\n";
   {
       BigExpensiveObject beo = simple_return_value();
       beo.Use();
   }

   cout << "\ntest 2:grab const ref to a temporary\n";
   {
       const BigExpensiveObject & beo = simple_return_value();
       beo.Use();
   }

   cout << "\ntest 3:proxy object created from function returning
temporary\n";
   {
       ConstRef p = simple_return_value();
       // AAARGH! the destructor gets called here, leaving a dangling
reference
       p.ref.Use();
   }

   cout << "\ntest 4:proxy object\n";
   {
       ConstRef p = proxy_return_value();
       // AAARGH! the destructor gets called here, leaving a dangling
reference
       p.ref.Use();
   }

   return 0;
}






Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/