C++ 为什么只有当左值具有模板演绎时,我才能将其绑定到通用引用?
我正在阅读Scott Meyers-高效的现代C++,尽管我理解当我可以也不能将左值引用绑定到通用引用时,我无法理解这背后的原因C++ 为什么只有当左值具有模板演绎时,我才能将其绑定到通用引用?,c++,C++,我正在阅读Scott Meyers-高效的现代C++,尽管我理解当我可以也不能将左值引用绑定到通用引用时,我无法理解这背后的原因 #include <iostream> #include <string> class A{ public: A(std::string && s){} }; class B{ public: template<typename T> B(T&& t){} }; int
#include <iostream>
#include <string>
class A{
public:
A(std::string && s){}
};
class B{
public:
template<typename T>
B(T&& t){}
};
int main()
{
std::string t;
//A a(t); //won't compile
B b(t); //compiles
return 0;
}
#包括
#包括
甲级{
公众:
(std::string&&s){}
};
B类{
公众:
模板
B(T&&T){}
};
int main()
{
std::字符串t;
//A(t);//不会编译
B(t);//编译
返回0;
}
我在传递
t
时没有看到任何未定义的行为,这是对A()
的左值引用,因此它被绑定为std::string&
。为什么仅仅通过类型推断就可以做到这一点?因为它不是转发(通用)引用。它是一个右值引用,右值引用不能绑定到左值 因为它不是转发(通用)引用。它是一个右值引用,右值引用不能绑定到左值 原因是在B
中,模板参数T
本身被允许为引用类型。在您的示例中,我相信编译器推断T
为std::string&
类型,这意味着在单态化之后,B
的构造函数将具有签名B(std::string&&T)
。然后,规则接管,它将std::string&&&
转换为std::string&
(如果您愿意,您可以认为:“从r值引用到l值引用就是l值引用”)。这与您试图调用构造函数的类型相匹配
另一方面,
A
坚持要给它一个std::string&
,而你没有,所以编译器拒绝了它。编译器必须拒绝它,因为假设当一个值通过r值引用(&&
)传递时,它实际上无法从任何其他范围访问。许多函数实现都依赖于这一假设,以允许它们有效地重用传递值的内部内存表示,而不是进行复制,因为它们知道没有其他东西依赖它(想想移动语义和std::swap
).原因是在B
中,模板参数T
本身被允许作为引用类型。在您的示例中,我相信编译器推断T
为std::string&
类型,这意味着在单态化之后,B
的构造函数将具有签名B(std::string&&T)
。然后,规则接管,它将std::string&&&
转换为std::string&
(如果您愿意,您可以认为:“从r值引用到l值引用就是l值引用”)。这与您试图调用构造函数的类型相匹配
另一方面,
A
坚持要给它一个std::string&
,而你没有,所以编译器拒绝了它。编译器必须拒绝它,因为假设当一个值通过r值引用(&&
)传递时,它实际上无法从任何其他范围访问。许多函数实现都依赖于这一假设,以使它们能够有效地重用传递值的内部内存表示,而不是进行复制,这是安全的,因为没有其他东西依赖于它(想想移动语义和std::swap
)。转发(通用)和引用和右值引用。示例中有右值引用。Scott Mayers应该在现代C++中详细解释它。
转发引用的主要特点是编译器可以确定它是右值还是左值。阅读有关引用折叠的更多信息。是一个很好的开始参考。Mayers也应该用有效的现代C++编写它。 < P>转发(通用)引用和RValk引用之间有很大的差别。Scott Mayers应该在现代C++中详细解释它。
转发引用的主要特点是编译器可以确定它是右值还是左值。阅读有关引用折叠的更多信息。是一个很好的开始参考。Mayers也应该用有效的现代C++编写它。 <代码> STD::String & & /Cord>是R值引用,而不是宇宙引用。Scott Meyers.BTW也尝试阅读:现在的正式术语是转发引用!(通用参考是一个用词不当)@engf-010不幸的是,我们仍然可以找到很多文章(同样来自Scott)称它们为通用的,这可能是相当错误的confusing@formerly当前位置这并不能消除我们必须使用正确术语的事实。(从现在到未来)。
std::string&&
是r值参考,而不是宇宙参考。请尝试阅读Scott Meyers的文章。顺便说一句:现在的官方术语是转发参考!(通用参考是一个用词不当)@engf-010不幸的是,我们仍然可以找到很多文章(同样来自Scott)称它们为通用的,这可能是相当错误的confusing@formerly当前位置这并不能消除我们必须使用正确术语的事实。(从现在到将来)。@engf-010问题是为什么只有模板,答案是引用崩溃。还是我误解了什么?Universal reference只是Mayer的名字,我知道:)但我已经习惯了这个名称。从c++17开始,以前称为Universal reference的东西就有了一个正式名称:转发引用(它准确地描述了正在发生的事情),它们没有任何通用性(错误的、令人困惑的名称)。@engf-010问题是为什么只有模板,答案是引用崩溃。还是我误解了什么?我知道,通用参考只是梅尔的名字:)但我已经习惯了那个名字,以前称为通用参考的东西