gpt4 book ai didi

c++ - 调用左值引用构造函数而不是右值引用构造函数

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:11:25 25 4
gpt4 key购买 nike

有这段代码:

#include <iostream>

class F {
public:
F() = default;
F(F&&) {
std::cout << "F(F&&)" << std::endl;
}
F(F&) {
std::cout << "F(F&)" << std::endl;
}
};

class G {
F f_;
public:
G(F&& f) : f_(f) {
std::cout << "G()" << std::endl;
}
};

int main(){
G g = F();
return 0;
}

输出是:

F(F&)
G()

为什么在 G 类的构造函数中调用 F(F&) 构造函数而不是调用 F(F&&) 构造函数? G类的构造函数的参数是F&& f,它是右值引用,但调用了左值引用的构造函数。

最佳答案

Why F(F&) constructor is called instead of F(F&&) constructor in constructor of class G?

因为 f是一个左值。即使它绑定(bind) 到一个右值,并且它的类型是对 F 的右值引用, 它也是一个命名变量。这使它成为左值。不要忘记对象的值类别不是由其类型决定的,反之亦然。

当您将左值传递给函数时,只能将左值引用绑定(bind)到它。如果您只想捕获右值,则应按如下方式更改代码:

class G {
F f_;
public:
G(F&& f) : f_(std::move(f)) {
std::cout << "G()" << std::endl;
}
};

或者,您可以使用 std::forward<>() ,这在这种情况下是等效的,但使您的意图转发 f更清楚:

class G {
F f_;
public:
G(F&& f) : f_(std::forward<F>(f)) {
std::cout << "G()" << std::endl;
}
};

现在这最后一个定义很容易扩展,所以 F 类型的左值和右值都是可以绑定(bind)到参数 f :

class G {
F f_;
public:
template<typename F>
G(F&& f) : f_(std::forward<F>(f)) {
std::cout << "G()" << std::endl;
}
};

例如,这允许构造 G 的实例这样:

F f;
G g(f); // Would not be possible with a constructor accepting only rvalues

虽然最后一个版本有一个警告:你的构造函数will basically work as a copy-constructor as well , 所以你可能想要显式定义所有可能的复制构造函数以避免尴尬的情况:

class G {
F f_;
public:
template<typename F>
G(F&& f) : f_(std::forward<F>(f)) {
std::cout << "G()" << std::endl;
}
G(G const&) = default;
G(G&); // Must be defaulted out-of-class because of the reference to non-const
};

G::G(G&) = default;

由于非模板函数优于函数模板的实例化,因此在构造 G 时将选择复制构造函数来自另一个对象 G目的。当然,这同样适用于move 构造函数。这留作练习。

关于c++ - 调用左值引用构造函数而不是右值引用构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15314727/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com