3

I'm trying to understand the exact behavior of object initialization in C++ when using a function that returns a reference to *this. Consider the following generic code:

class T {
public:
    T& func() { /* do something */ return *this; }
};

const T obj = T().func();

And a concrete example using std::string:

const std::string fullName = std::string(firstName).append(" ").append(lastName);

Does the fact that the methods return a reference to a temporary object affect whether the copy or move constructor is used?

My understanding is that the copy constructor is called because the functions return an lvalue reference and the compiler can not know that it is from a temporary object.

However, I'm curious about potential optimizations and whether there are any nuances I'm missing.

I currently use

const T obj = std::move(T().func());

and in case of std::string I would use

const std::string fullName = std::string(firstName) + " " + std::string(lastName);
5
  • const T obj = T().func(); obj will be a copy of T (copy of a reference to a const instance). It is not the same as what std::string::append() does. The will update internal data of the string class and then returns a reference to the same object (that now has updated content) Commented Dec 12, 2024 at 18:09
  • For std::move to actually do something you would need to implement a move constructor on T. Commented Dec 12, 2024 at 18:11
  • For efficient string concatenation use std::format and std::move. Using + like you do now, will construct and destruct unecessary std::string instances. e.g. const std::string fullName{std::move(std::format("{} {}", firstName, lastName))}; Commented Dec 12, 2024 at 18:12
  • 3
    If you do this a lot with your own types, you could have two funcs with different ref-qualifiers. One const T& func() const& and one T&& func() && (in which you then return std::move(*this);). That way you won't need std::move(T().func()). It'll select the correct overload automatically if you just do const T obj = T().func();. Commented Dec 12, 2024 at 18:16
  • 1
    A move is only useful for types that have managed resources. If T has no managed resources, then a move is the same as a copy. Commented Dec 12, 2024 at 18:48

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.