C ++模板函数,替换失败跳过实现

时间:2014-03-13 03:04:55

标签: c++ template-specialization

我有以下代码仅用于测试,模板函数使用两次,第一次没问题。在第二种情况下,我创建一个指针并将指针作为参考传递给模板函数。我期待这条线" obj。~T()"编译时失败。但实际上代码编译并运行良好。当我通过函数调试时,程序只是跳过obj。~T();我正在使用VC10。

我的问题是:
这是预期的行为吗?如果它基于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;
}

3 个答案:

答案 0 :(得分:6)

这是一个显式析构函数调用,它是一个有效的操作,虽然不一定被认为是一个好习惯。如果可能的话,可以考虑使用范围变量。

在你的第二次调用中,你实际上是在尝试调用指针析构函数,它确实不存在,而不是指向对象的析构函数,这就是它跳过它的原因。但是,请注意,您的Dummy对象在第二次调用后仍然会被分配,并且您将在所有情况下泄漏。

答案 1 :(得分:4)

模板替换导致伪析构函数调用表达式或析构函数的函数调用。这些是语言语法中相同的东西,但在语义上不同:

  • 对于诸如指针之类的基本类型,允许使用伪析构函数调用(C ++11§5.2.4),它不执行任何操作。

  • 显式析构函数调用是一个函数调用,它通过名称查找并形成一个函数调用表达式(C ++11§5.2.2)。

与模板中伪析构函数调用的语法相匹配的任何内容也可能是格式良好的函数调用(显式析构函数调用),反之亦然。

因此,如果您看到d的析构函数和dp的没有消息,则表示您正在观察预期的行为。

答案 2 :(得分:1)

无编译错误
- 行为正确为 obj。~T(); 表示对对象的函数调用。调用函数不是编译错误。

代码运行正常
- 此行为未定义。为什么你没有在运行时得到任何错误是因为它是一个非常简单的类,甚至没有原始类型的数据成员,更不用说复杂的类型成员了。
这里发生的是在Main中,对象d被调用两次析构函数。一次调用ptrDest,并在退出main函数时进行第二次隐式破坏。 析构函数是如此简单的编译器将其代码内联。这只是一个无害的cout。如果你对复杂的类使用析构函数对数据成员执行某些操作,那肯定会导致问题。