为什么移动的 class 对象在绑定到函数参数时不触发移动构造函数?

Why does a moved class object not trigger the move constructor when bound to function parameter?

假设

现在,如果 foo 的参数类型为 A,则调用移动构造函数(这是预期的,因为 A&& 作为参数传递给函数-本地 A).

但是在A&&的情况下,没有调用移动构造函数,实际上没有调用构造函数。为什么?

我原以为这是由于复制省略而发生的,但它也发生在为 gcc 设置了 -O0 标志的情况下。我还认为 && 基本上只是 flags 参数列表中用于重载决策的右值,因为在函数体内,它被视为左值。但这意味着左值 A 将绑定移动的 A&& 并且应该再次调用移动构造函数。我错过了什么?

CODE

在 x86-x64 gcc 11.2 下编译

#include <iostream>
#include <string>
#include <string.h>

struct A
{
    char * str_;
    A() {
        std::cout << "normal constructor called\n";
        str_ = new char[7];
        sprintf(str_, "Hello!");
    }
    ~A(){ delete[] str_; }

    A(A& copy) {
        std::cout << "copy constructor called\n";
        str_ = strdup(copy.str_);
    }

    A(A&& moved) {
        std::cout << "move constructor called\n";
        str_ = moved.str_;
        moved.str_ = nullptr;
    }
};


void foo(A&& a)
{
    std::cout << a.str_ << "\n";
}

int main()
{
    A obj;

    foo(std::move(obj));
}

foo 采用 A&& 时,您将绑定到 r-value 引用,而不是创建任何需要构造的新 A 对象。
这是因为 std::move 基本上只是对 r-value 引用的转换。
foo 采用 A 时,您将 r-value 引用传递给 A 作为构造 A 的一种方式。在这里,选择移动构造函数,因为它以 A&& 作为参数。