1

Here is the definition of SimpleString. It implements both copy constructor and move constructor.

struct SimpleString {
  SimpleString(size_t max_size)
      : max_size{ max_size }
      , length{}  {
    if(max_size == 0) {
      throw std::runtime_error{ "Max size must be at least 1." };
    }
    buffer = new char[max_size];
    buffer[0] = 0;
  }
  ~SimpleString() {
    delete[] buffer;
  }
  SimpleString(const SimpleString& other)
      : max_size{ other.max_size }
      , buffer{ new char[other.max_size] }
      , length{ other.length } {
        puts("copy constructor");
    std::strncpy(buffer, other.buffer, max_size);
  }
  SimpleString(SimpleString&& other) noexcept
      : max_size(other.max_size)
      , buffer(other.buffer)
      , length(other.length) {
        puts("move constructor");
    other.length = 0;
    other.buffer = nullptr;
    other.max_size = 0;
  }

  void print(const char* tag) const {
    printf("%s: %s", tag, buffer);
  }
  bool append_line(const char* x) {
    const auto x_len = strlen(x);
    if(x_len + length + 2 > max_size)
      return false;
    std::strncpy(buffer + length, x, max_size - length);
    length += x_len;
    buffer[length++] = '\n';
    buffer[length] = 0;
    return true;
  }

  size_t max_size;
  char* buffer;
  size_t length;
};

I implement + operator.

SimpleString operator+(const SimpleString& str_1, const SimpleString& str_2) noexcept {
    SimpleString str_3{str_1}; // copy
    str_3.append_line(str_2.buffer);
    str_3.buffer[str_3.length-1]='\0';
    return str_3;
}

Does this function return an rvalue?

In c++ primer(5th):

Functions that return a nonreference type, along with the arithmetic, relational, bitwise, and postfix increment/decrement operators, all yield rvalues.

So I think operator+ return an rvalue.

int main() {
  SimpleString a{ 50 };
  a.append_line("We apologise for the");
  SimpleString b{ 50 };
  b.append_line("Last message");
    auto c = a+b; // copy constructor
    c.print("c");
}

I thought it would call the move constructor and print move constructor, because a+b is an rvalue.

But the output is:

copy constructor
c: We apologise for the
Last message

Why the move constructor is not called?

Tokubara
  • 392
  • 3
  • 13

1 Answers1

1

Because of copy elision, or else return value optimization (RVO) here!

It happens because the class type and the returned type are the same types.

So, the compiler instead of constructing the object str_3 in a place in memory, and afterward copy/move it, it (more optimally) construct it in-place!

I think you can enforce the usage of the move constructor by specifying:

return std::move(str_3)

I had the same question in the past, but for some reason they closed it... here!