c++模板函数,替换失败跳过实现
C++ template function, substitution failure skip the implementation
我有下面的代码只是为了测试,模板函数使用了两次,第一次它是ok的。在第二种情况下,我创建一个指针,并将指针作为引用传递给模板函数。我期望"obj.~T()"行在编译时失败。但实际上代码编译和运行得很好。当我调试该函数时,程序只是跳过obj.~T();我用的是VC10。
我的问题是:1. 这是一种预期行为吗?如果它是基于c++标准的哪个部分?
2. 这种行为有什么利弊吗?在我的情况下,它是好的,因为没有编译错误,也没有运行时错误。但是可能会有一些我不知道的情况,但是会损坏代码。
谢谢
template<typename T>
void ptrDest(T& obj)
{
obj.~T();
}
class Dummy
{
public:
Dummy(){}
~Dummy(){ cout << "dest" <<endl;}
};
int main()
{
Dummy d;
ptrDest(d);
Dummy* pd = new Dummy();
ptrDest(pd);
return 0;
}
这是一个显式析构函数调用,它是一个有效的操作,尽管不一定被认为是一个好的实践。如果可能的话,考虑使用有作用域的变量。
在第二个调用中,您实际上试图调用指针的析构函数,而不是指向对象的析构函数,这就是它跳过它的原因。但是,请注意,在第二次调用之后仍然分配Dummy对象,并且在所有情况下都将泄漏。模板替换导致伪析构函数调用表达式或函数调用析构函数。它们在语言语法中是相同的东西,但在语义上不同:
-
伪析构函数调用(c++ 11§5.2.4)是允许的基本类型,如指针,它不做任何事情。
-
显式析构函数调用是经过名称查找并形成函数调用表达式的函数调用(c++ 11§5.2.2)。
任何与模板中伪析构函数调用的语法相匹配的内容也可能是格式良好的函数调用(显式析构函数调用),反之亦然。
因此,如果您看到d
的析构函数有两条消息,而dp
的析构函数没有消息,那么您正在观察预期的行为。
没有编译错误
-行为是正确的,因为obj.~T();表示它是对对象的函数调用。调用函数不是编译错误。
代码运行正常
-此行为未定义。为什么你没有得到任何错误运行是因为它是一个非常简单的类,甚至没有基本类型的数据成员,更不用说复杂类型的成员。
这里发生的事情是,在Main中,对象d的析构函数被调用了两次。一次是调用ptrDest,第二次是退出Main函数时的隐式析构函数。析构函数是如此简单,编译器将其代码内联。这只是一个无伤大雅的理由。如果在复杂类中使用析构函数对数据成员进行操作,则肯定会导致问题。
- 如果没有malloc,链表实现将失败
- 单元测试欧拉到四元数实现失败
- CMake + Qt,moc 编译失败,无法实现 QMetaObject 方法(编译器找不到基本 ui 对象的标头?
- 使用双LL在C++中实现Stack失败,出现异常"EXC_BAD_ACCESS(代码=2,地址=0x7fff5
- C++ 链表合并排序的实现在连接 1 个以上节点的子列表时失败
- 有没有一种很好的方法来实现具有默认失败情况的条件类型?
- std::tuple的实现是否允许在触发空类元素的派生到基转换时失败
- 在某些情况下,我的快速排序实现失败
- 使用链接列表实现堆栈,调试断言失败
- 如何在应该失败的CMake中实现编译测试
- WinAPI 如何确保在未实现 WinMain 时编译失败
- 带有实现的纯虚拟函数在XCode中失败
- Boost multiprecision失败是因为complex的实现试图在_Isinf或_Isnan等内部函数中强制转
- cpp -尝试实现触摸功能时断言失败
- 使用Objective-C和C++实现X-FACEBOOK-PLATFORM身份验证失败
- 为什么QueryInterface()会失败,当接口确实在Windows中实现并具有内置编组器时
- Swapcontext在多对多线程实现中失败
- 试图在c++中实现一个堆栈模板(失败得很惨)
- c++多线程优先级实现失败
- 为什么我的简单快速排序实现失败时,等效的元素在数组中