push_back
的以下代码失败,emplace_back
成功:
#include <vector>
volatile int x = 0;
int main()
{
std::vector<int> vec;
vec.emplace_back(x);
vec.push_back(x); // error: no matching function for call to 'std::vector<int>::push_back(volatile int&)'
}
我理解push_back
错误,因为它需要引用并试图从该引用中隐式抛弃volatile
限定符。
但是,emplace_back
也接受引用(rvalue-references是引用)。为什么区别对待?
答案 0 :(得分:8)
这是因为它们在C ++ 11标准中的定义方式。第23.3.6.1段规定了他们的签名:
template <class... Args> void emplace_back(Args&&... args);
void push_back(const T& x);
void push_back(T&& x);
虽然push_back()
的可用重载参数没有任何volatile
限定,但emplace_back()
函数模板的参数可以绑定到任何cv
的左值 - 资格。
但是,emplace_back也需要引用(rvalue-references是引用)。为什么它的处理方式不同?
是的,因为emplace_back()
是一个函数模板,类型推导会推断Args
是一个长度为1的参数包,其唯一元素的类型为{{1 (见第14.8.2.1/3段)。
另一方面,int volatile&
的重载是push_back()
类模板的常规成员函数,并且在调用它们时不会进行类型推导。由于对非std::vector<>
的引用无法绑定到限定为volatile
的对象(请参阅第8.5.3 / 4-5段),编译器将无法解析该调用。