【问题标题】:C++ template function to delete and reset pointers用于删除和重置指针的 C++ 模板函数
【发布时间】:2016-12-19 15:17:22
【问题描述】:

我刚刚遇到了一个关于指针的小问题。 因为我想用一种快速简便的方法在一行中完成这项任务:

...
delete pointer;
pointer = 0;
...

我只是快速设置了一个简单的头文件,其中包含一个接受任何类型指针的模板方法。它看起来像这样:

#ifndef P_DELETE_H
#define P_DELETE_H

template <typename T>
void pDelete(T* pointer) {
  if (pointer) {
    delete pointer;
    pointer = 0;
  }
}

#endif

但是,结果不符合我对删除对象和重置指针的期望。相反,似乎只删除了对象,但将其设置为零没有效果(这是我需要的)。如果这里有人可以减轻我的负担并解释这种行为,我会非常感谢!

更新:

正如答案所解释的,使用 std::unique_ptr 和 std::shared_ptr 是比取消 this 指针更安全的方法。

但如果你真的需要按照我的要求走,下面的代码就可以了:

template <typename T>
inline void pDelete(T*& pointer) {
  if (pointer) {
    delete pointer;
    pointer = 0;
  }
}

然而,这通常是不安全的,即使它正确地删除并取消了所有实例上的指针(快速测试揭示了这一点)。

感谢大家提供的信息丰富的答案!

【问题讨论】:

  • 函数参数在函数范围内是本地的。这包括指针。您必须使用指针引用或指针指针来影响函数外部的值。 (或者停止使用原始指针,你就不需要这整件事了。)
  • 使用智能指针库(如std::unique_ptr)完全无需编写此类代码。
  • 我支持智能指针方法。这种方法容易出错。例如,如果您传递一个使用 new[] 分配的指针,您将有未定义的行为。
  • 需要这样的编码技巧通常是糟糕设计的结果。
  • @Migsi 实际上 unqiue_ptr 应该是默认访问。唯一的开销是删除调用,无论如何您都需要这样做,因此您不妨利用 RAII。

标签: c++ templates pointers delete-operator


【解决方案1】:

您正在寻找的解决方案是:

delete pointer;
pointer = nullptr;

是的,只需内联编写代码即可。真的没有理由在某个地方引入另一个函数模板,人们必须查看它才能弄清楚它实际上做了什么,只是为了节省一行代码。

以上内容完全可读且易于理解。

【讨论】:

  • 但是,您忘记提及上面的内容还没有实际意义。如果在删除后清空指针有任何好处,它们将自动清空。
  • @SergeyA 当然有好处。只是通常您不需要这种好处,这就是它们不会自动归零的原因。
  • '通常你不需要好处' - 完全正确。
  • 在我的情况下,我需要这个好处来处理一些事情。仅当将某个指针设置为 nullptr 时才可能检查某个指针是否已清除,任何其他值都假定它仍被设置。无论如何,有一个模板这样做可以防止在长的析构函数中出现拼写错误,应该清除大量的指针。
  • @Migsi 听起来您需要代码重构。除非您正在编写自己的基本容器类型,否则大量手动指针管理通常是糟糕设计的标志。
【解决方案2】:

您尝试做的整件事都没有实际意义。你有没有想过为什么这不会自动发生?为什么删除后运行时不会使指针无效?因为 C++ 标准委员会不够聪明?

没有。因为大多数时候它对你没有好处。是的,您使指针的这个实例无效-但是您以指针开头的全部原因很可能是该指针在其他地方生活得很好! (当然也有例外)。结果,您的所有无效化都使您免于对指针的此实例的不正确访问-但在任何其他实例上都没有。本质上,它会给你一种虚假的安全感。

与其陷入虚假的安全感,不如采用自动指针 - std::unique_ptr 应该是首选,如果还不够,std::shared_ptr - 但要确保你真的需要它!

【讨论】:

  • 如果你能解释我如何在 QT 中最好地使用 shared_ptr,我现在就改用它们。我知道使用这些更安全、更清洁,但是在我需要涉及 qt 函数的地方,这对我来说似乎毫无意义。
  • @Migsi,我对 Qt 了解不多,但据我了解,Qt 有自己的智能指针功能?
  • @Migsi 如果您在处理 QT 对象时直接调用 delete,那么确实没有理由不假设通常用于 std::unique_ptrstd::shared_ptr 的相同模式不适用于你的情况。
  • @Xirema 所以你是说我可以像处理自定义对象指针一样处理 QT 对象指针,并且当我将原始指针作为参数提供给 QT 函数时不需要担心?如果那是对的,我会很高兴!
【解决方案3】:

停止使用原始指针来表示所有权。如果您通过指针获取对象的所有权,它应该进入std::unique_ptr

那么你的情况就是pointer.reset()

如果你想让其他代码观察你拥有的对象,而不转移所有权,你可以使用pointer.get() 来获取一个非拥有的指针。您也可以使用*pointer 获取参考。

如果您必须通过使用原始指针的接口(我在看您,Qt)传递该所有权,请使用pointer.release()

【讨论】:

  • 所以我应该“.release()”所有指针进入QT?另外,什么时候我什至需要关心我给 QT 或从 QT 获得的指针?文档通常使这一点很不清楚......
  • 好吧,如果您之前不清楚原始指针,您要么泄漏,要么重复删除。在这方面没有任何改变。 Qt 通常只通过“父/子”关系突变器中的指针转移所有权
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-18
  • 2016-01-07
  • 1970-01-01
相关资源
最近更新 更多