With the following code, "hello2" is not displayed as the temporary string created on Line 3 dies before Line 4 is executed. Using a #define as on Line 1 avoids this issue, but is there a way to avoid this issue without using #define? (C++11 code is okay)
#include <iostream>
#include <string>
class C
{
public:
C(const std::string& p_s) : s(p_s) {}
const std::string& s;
};
int main()
{
#define x1 C(std::string("hello1")) // Line 1
std::cout << x1.s << std::endl; // Line 2
const C& x2 = C(std::string("hello2")); // Line 3
std::cout << x2.s << std::endl; // Line 4
}
Clarification:
Note that I believe Boost uBLAS stores references, this is why I don't want to store a copy. If you suggest that I store by value, please explain why Boost uBLAS is wrong and storing by value will not affect performance.
Expression templates that do store by reference typically do so for performance, but with the caveat they only be used as temporaries
Taken from the documentation of Boost.Proto (which can be used to create expression templates):
In your initial example this means that you should do:
That way the
C
temporary never outlives thestd::string
temporary. Alternatively you could makes
a non reference member as others pointed out.Since you mention C++11, in the future I expect expression trees to store by value, using move semantics to avoid expensive copying and wrappers like std::reference_wrapper to still give the option of storing by reference. This would play nicely with
auto
.A possible C++11 version of your code:
This would mean that code like
C("hello").get()
would only allocate memory once, but still play nice withAfter your edit:
Storing by reference is dangerous and error prone sometimes. You should do it only when you are 100% sure that the variable reference will never go out of scope until its death.
C++
string
is very optimized. Until you change a string value, all will refer to the same string only. To test it, you can overloadoperator new (size_t)
and put a debug statement. For multiple copies of same string, you will see that the memory allocation will happen only once.You class definition should not be storing by reference, but by value as,
If this question is meant for general sense (not specific to string) then the best way is to use dynamic allocation.
Yes.
Define your class as: (don't store the reference)
Store the copy!
Demo : http://www.ideone.com/GpSa2
The problem with your code is that
std::string("hello2")
creates a temporary, and it remains alive as long as you're in the constructor ofC
, and after that the temporary is destroyed but your objectx2.s
stills points to it (the dead object).Without looking at BLAS, expression templates typically make heavy use of temporary objects of types you aren't supposed to even know exists. If Boost is storing references like this within theirs, then they would suffer the same problem you see here. But as long as those temporary objects remain temporary, and the user doesnt store them for later, everything is fine because the temporaries they reference remain alive for as long as the temporary objects do. The trick is you perform a deep copy when the intermediate object is turned into the final object that the user stores. You've skipped this last step here.
In short, it's a dangerous move, which is perfectly safe as long as the user of your library doesn't do anything foolish. I wouldn't recommend making use of it unless you have a clear need, and you're well aware of the consequences. And even then, there might be a better alternative, I've never worked with expression templates in any serious capacity.
As an aside, since you tagged this C++0x,
auto x = a + b;
seems like it would be one of those "foolish" things users of your code can do to make your optimization dangerous.