So which one to use roughly depends on a trade-off between efficiency (return by const&) and encapsulation (return by value).
If I have a large/complex object, I will prefer returning const& for efficiency purposes. There is, however, a third option in this case: delegation. Instead of returning a const& of that big object, I can write methods like int getTracerAttribute() { return m_tracerInfo.getAttribute(); } and hide the fact that I'm holding on to a Tracer instance called m_tracerInfo. The advantage of delegation is, you get encapsulation of the Tracer object. The disadvantage is, if you need to access a lot of methods in the Tracer object, you get code bloat. As noted, if you want to return by const&, you must ensure that the returned reference will actually point to some valid memory (eg
not an automatic variable inside the method).
For small objects like std::string, you may want to return by value. The ugly thing about return by value is, you may have to pay for an extra copy-construction upon return. But there is a trick. Read this:
http://www.informit.com/articles/article.aspx?p=25033&seqNum=3
If you call the constructor at return, many compilers will optimize away that extra copy-construction.
So what is better really depends on the context of what you're trying to accomplish. One of the advantages of (and difficulties of learning) C++ is having the choice to pick the implementation most appropriate for what you are trying to accomplish.