Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么只有当左值具有模板演绎时,我才能将其绑定到通用引用?_C++ - Fatal编程技术网

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

我正在阅读Scott Meyers-高效的现代C++,尽管我理解我可以也不能将左值引用绑定到通用引用时,我无法理解这背后的原因

#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问题是为什么只有模板,答案是引用崩溃。还是我误解了什么?我知道,通用参考只是梅尔的名字:)但我已经习惯了那个名字,以前称为通用参考的东西