Prev: Can const& functors be passed to functions efficiently (i.e. inlined, etc)?
Next: Temporaries passed to constructor yield invalid member references
From: Razvan Cojocaru on 30 May 2010 06:07 > template <class StringT> > struct A > { > A (StringT const &str) : str(str) { } > StringT const &str; > }; > The problem is that the constructor allows passing temporaries, which > get destroyed as soon as the constructor finishes executing, not after > the object is destroyed. > > Please let me know if you have any better solutions to my problem. That seems like a rather convoluted way of trying to achieve this (template part ommited as it seem irrelevant for the purposes of our discussion): struct A { A(const std::string& s) : str(s) {} /* const, if you prefer */ std::string str; } Why is it terribly important to have a reference struct member, instead of a regular string? Even if you're using (non-const) references, you should be aware that if the string you're referring to in the struct goes out of scope (destroyed) somewhere, and the struct instance doesn't, you still have a big problem. So the safest (and simplest) way is to simply copy the contents of the constructor string to the member data string (if nothing else, because how else would you cover the case you've described, where a temporary string gets constructed when passed to A(), then destroyed?). Cheers, -- Razvan Cojocaru KeyID: 0x04CA34DE [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Razvan Cojocaru on 31 May 2010 00:11 > Use a const pointer. Use it for the argument passing and if it's not too > much hassle also use it for the member. > > Bottom line for me is: Always use pointers for these parameters. > Use a pointer member in "90%" of cases. I don't see the difference between his problem using a non-const reference and what would ensue if he uses a const pointer (since a reference is pretty much the functional equivalent of a const pointer, dereferencing and checking for NULL aside). -- Razvan Cojocaru KeyID: 0x04CA34DE [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Martin B. on 1 Jun 2010 02:59 Goran wrote: > On May 30, 1:39 am, M Stefan <mstefa...(a)gmail.com> wrote: >> Hello. I am trying to write a class similar to this: >> template <class StringT> >> struct A >> { >> A (StringT const &str) : str(str) { } >> StringT const &str;}; >> >> The problem is that the constructor allows passing temporaries, which >> get destroyed as soon as the constructor finishes executing, not after >> the object is destroyed. >> (....) >> Please let me know if you have any better solutions to my problem. > > In languages like C and C++, there are no, zilch, nada solutions. You > have to handle lifetime of your stuff at any point manually. That's > how the language works, so use it that way. You passed a temporary and > stored a reference to it. That does not work, end of. > > Goran. > > P.S. Martin B's "solution" isn't, e.g. > > class x > { public: > x(const TYPE* p) : _r(*p) {} > TYPE& _r; > }; > > is broken with > > x(NULL); // bad x._r, no help from compiler > > and > > x(&TYPE()); // bad x._r, no help from compiler > I never ever claimed that my proposal is a solution to lifetime management! What I continue to claim is that /if/ you need to reference any object like in the OP, then you should use a pointer [1], because the conversion rules for (const-)references make it nearly impossible to get it right. br, Martin [1]: Yes, a smart-pointer would be best, but that's not always possible. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Dragan Milenkovic on 1 Jun 2010 02:50
Dragan Milenkovic wrote: > M Stefan wrote: >> Hello. I am trying to write a class similar to this: >> template <class StringT> >> struct A >> { >> A (StringT const &str) : str(str) { } >> StringT const &str; >> }; >> The problem is that the constructor allows passing temporaries, which >> get destroyed as soon as the constructor finishes executing, not after >> the object is destroyed. >[snip] > IMHO, it's best to clearly document the purpose and functionality of A. > > And now for other solutions. Clearly, the C++ way to do things is > as in your "solution 3". You worry too much about performance. I didn't read carefully. You want to change only the constructor, while I had in mind changing only the member field. So, either make it StringT or shared_ptr<StringT> or pointer/reference and write a nice documentation. Someone else argumented that making it a pointer is not different than making it a reference. Well, apart from gaining operator= (should one need it), you might also force a (clueless) user actually _think_ about what he/she is doing while typing operator "&". :-) -- Dragan [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |