右值引用作为参数调用移动构造函数吗?

问题描述 投票:0回答:2

我正在学习 C++ 移动语义,但我无法理解下面的代码:

#include <iostream>
class A {
    public:
        A() { std::cout << "Default Constructor\n"; }
        A(const A& other) { std::cout << "Copy Constructor\n"; }
        A(A&& other) noexcept { std::cout << "Move Constructor\n"; }
    
        // 仅仅是为了避免编译器优化而定义
        A& operator=(const A& other) {
            std::cout << "Copy Assignment Operator\n";
            return *this;
        }
        A& operator=(A&& other) noexcept {
            std::cout << "Move Assignment Operator\n";
            return *this;
        }
    };
    
    void func(A&& a) {
        // Do something with 'a'
    }
    
    int main() {
        A a;  // 调用默认构造函数
        func(std::move(a));  // 调用移动构造函数
        func(A());  // 直接传递右值,调用移动构造函数
        return 0;
    }

输出为:

Default Constructor
Default Constructor

为什么移动构造函数没有被调用?为什么只调用两个默认构造函数?

编译器是“g++ 13.2”

image

c++
2个回答
0
投票
void func(A&& a) { }

int main() {
        A a;  // default constructor
        func(std::move(a));  // you are merely creating a reference that allows moving.
                             // Your func doesn't do anything with it, so no object is created/moved.
        func(A());  // again, you create an object (default constructor), then pass it
                    // to func() as a reference that would allow moving.
        return 0;
    }

如果您将

func
更改为实际对象,情况将会非常不同:

void func(A a) { }

现在,您的动作实际上将用于填充新的

a

func(a);               // copy your a into the function parameter
func(std::move(a));    // move your a into the function parameter

0
投票

我想知道为什么移动构造函数不被调用?并且只调用了两个默认构造函数?

您的示例中没有任何内容需要对

A
类型的对象使用 move ctor。特别是,
A a;
默认初始化,因此将使用默认构造函数。

此外,调用

std::move
中的
func(std::move(a));
只是返回右值引用,实际上并不移动或创建对象。

最后,调用

func(A()); 
首先使用
A()
部分的默认构造函数,这会产生一个可以直接绑定到
A&&
参数的右值表达式。这里再次不需要调用/使用 move ctor。

© www.soinside.com 2019 - 2024. All rights reserved.