C++ 右值引用与移动构造

问题提出

struct Base {
    Base() {std::cout << "ctor" << std::endl;}
    Base(const Base& b) {std::cout << "copy ctor" << std::endl;}
    Base(Base&& b) {std::cout << "move ctor" << std::endl;}
    ~Base() {std::cout << "dtor" << std::endl;}
};

template<typename T>
Base default_test(T&& a) {
    return Base(a);
}

int main() {
	default_test(Base {});
	return 0;
}

如上,定义一个类Base,并实现构造函数,复制构造函数与移动构造函数。T&&为引用折叠,根据main函数中default_test(Base {}),形参a是一个右值引用。那么在default_test中利用a构造一个Base实例时,会调用哪一个构造函数呢?
事实上,其输出为

ctor
copy ctor
dtor
dtor

如何使其利用移动构造函数呢?

使用static_cast或者std::forward

#include <iostream>

struct Base {
    Base() {std::cout << "ctor" << std::endl;}
    Base(const Base& b) {std::cout << "copy ctor" << std::endl;}
    Base(Base&& b) {std::cout << "move ctor" << std::endl;}
    ~Base() {std::cout << "dtor" << std::endl;}
};

template<typename T>
Base default_test(T&& a) {
    // Although the input is rvalue reference, but use `copy` not `move`
    return Base(a);
}

template<typename T>
Base cast_test(T&& a) {
    return Base(static_cast<Base&&>(a));
}

template<typename T> 
Base forward_test(T&& a) {
    return Base(std::forward<Base>(a));
}

int main() {
    std::cout << "First, we do nothing!\n";
    default_test(Base {});
    std::cout << "Second, we cast the input argument!\n";
    cast_test(Base {});
    std::cout << "Finally, use std::forward!\n";
    forward_test(Base {});   

    return 0;
}

输出如下:

First, we do nothing!
ctor
copy ctor
dtor
dtor
Second, we cast the input argument!
ctor
move ctor
dtor
dtor
Finally, use std::forward!
ctor
move ctor
dtor
dtor

可见在使用static_cast或者std::forward之后,可以成功调用move ctor而非copy ctor

小结

能够完美的保留输入参数的左右值引用,便是std::forward的一大用处。如上例,虽然输入参数为右值引用,但是右值引用本身在函数体中是可以取地址的,并不是一个右值。所以需要static_cast或者std::move或者std::forward,但需要注意的是,前两者是强转为右值引用或者使用了移动语义。

环境

使用编译器下载链接提供的GCC 12.2.0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值