在VC ++ 2013的C ++头文件memory
中,我发现类unique_ptr
的定义如下:
template<class _Ty, class _Dx> // = default_delete<_Ty>
class unique_ptr
{
...
};
令我困惑的是:模板参数没有默认类型,这是C ++ 11标准所要求的。 (见here)
但是,我可以编译以下代码而不会出现任何警告或错误:
#include <memory>
using namespace std;
int main()
{
unique_ptr<int>(new int); // Should be OK! ???
// rather than unique_ptr<int, default_delete<int>>(new int);
}
为什么?
答案 0 :(得分:4)
默认参数在先前的前向声明中指定:
// [memory:24]
_STD_BEGIN
#if _HAS_CPP0X
template<class _Ty>
struct default_delete;
template<class _Ty,
class _Dx = default_delete<_Ty> >
class unique_ptr;
#endif /* _HAS_CPP0X */
// [...]
// [memory:1276]
// TEMPLATE CLASS unique_ptr SCALAR
template<class _Ty,
class _Dx> // = default_delete<_Ty>
class unique_ptr
: private _Unique_ptr_base<_Ty, _Dx,
is_empty<_Dx>::value
|| is_same<default_delete<_Ty>, _Dx>::value>
{ // non-copyable pointer to an object
这是有效的,因为在定义之前声明函数的默认参数是有效的,例如
void foo(int x = 5);
void foo(int x) { /* ... */ }
[C++11: 14.1/10]:
可以与模板声明或定义一起使用的默认 template-arguments 集合是通过合并定义中的默认参数(如果在范围内)和所有声明中的声明来获得的。范围与默认函数参数相同(8.3.6)。 [例如:template<class T1, class T2 = int> class A; template<class T1 = int, class T2> class A;
相当于
template<class T1 = int, class T2 = int> class A;
-end example]
答案 1 :(得分:2)
我可以访问VS 2012,这就是我所看到的:
#if _HAS_CPP0X
template<class _Ty>
struct default_delete;
template<class _Ty,
class _Dx = default_delete<_Ty> >
class unique_ptr;
#endif /* _HAS_CPP0X */
因此声明具有默认模板参数。作为C ++中的一般规则,如果在前向声明中指定了default参数,则定义不需要重复默认参数。我记得如果在声明和定义中都指定了默认参数值,编译器会发出错误。