为什么用右值初始值设定项调用复制构造函数而不是移动构造函数

  • 本文关键字:构造函数 调用 复制 移动 c++
  • 更新时间 :
  • 英文 :


以下是SimpleString的定义。它同时实现了复制构造函数和移动构造函数。

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;
};

我实现了+运算符。

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]='';
return str_3;
}

这个函数是否返回右值?

在c++引物中(第5个(:

返回非引用类型的函数,以及算术、关系、逐位和后缀递增/递减运算符,都会产生右值。

所以我认为operator+返回了一个右值。

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");
}

我想它会调用move构造函数并打印move constructor,因为a+b是一个右值。

但输出是:

copy constructor
c: We apologise for the
Last message

为什么不调用move构造函数?

因为复制省略,或者返回值优化(RVO(在这里

之所以会发生这种情况,是因为类类型和返回的类型是相同的类型。

因此,编译器不是在内存中的某个位置构造对象str_3,然后复制/移动它,而是(更优化地(在适当的位置构造它!

我认为您可以通过指定来强制使用move构造函数

return std::move(str_3)

我过去也有同样的问题,但出于某种原因,他们关闭了它…在这里!

最新更新