【问题标题】:C - casting pointer to pointer to void [closed]C - 将指针转换为指向 void 的指针
【发布时间】:2014-11-29 18:58:17
【问题描述】:

编辑我不需要解决问题,我想知道是否以及为什么我应该更喜欢一件事而不是另一件事。函数声明不能更改

我有一个 C++ 项目,我需要编写一些代码,这些代码将由用 C 编写的代码调用。我有一个名为 A 的类,我需要实现一个方法来销毁由new,并使指针本身无效。

声明如下:

void destroy_A(void** a);

我需要一个void**,这样我就可以取消*a

我应该使用以下哪一项(如果有),为什么

delete *(A**)a;
delete *((A**)a);
delete (A*)*a;

编辑:也许我不清楚:我不知道技术术语,但我确实使用delete而不是free,并且实际方法是通过用 C 编译的代码调用的。否则,我不需要 void**

这是我的 CS 教员要求,作业不是我写的 :)

【问题讨论】:

  • 实际使用的new 语句是什么?通常不需要任何演员表。您可能需要区分 new()new[] 以及它们对应的 deletedelete[] 调用。
  • 首先,不要将指针归零。它不会为您买任何东西,并使您的界面复杂化。以及为什么需要强制转换,最好为 C 使用不透明类型(又名 A 的前向声明为 struct)。
  • @Deduplicator:什么?删除指针后将其归零是常见的做法。它消除了悬空指针。
  • @LightnessRacesinOrbit:不在您作为基本构建块提供的接口功能中。 freedelete 都没有这样做是有原因的。
  • @Deduplicator:OP 试图创建的这个函数既不是free 也不是delete。它是它们的包装,不是“基本构建块”。显然,需要额外的功能。为什么不将该功能作为您在呼叫站点上的唯一附加功能?

标签: c++ c pointers casting void


【解决方案1】:

这三个都有效。你要找的,到底是什么

A* somePtr = ...; // get a pointer to your object
delete somePtr;   // delete the object it points to

您的三个选项复制如下,每个选项都分成多行以突出它们的作用:

delete *(A**)a;

A** ptrToPtrToA a = (A**)a;
A*  ptrToA a2 = *ptrToPtrTo_a;
delete ptrTo_a;

这里没问题。我们最终正确地解除了对象的引用

delete *((A**)a);

A** ptrToPtrTo_a = (A**)a;
A*  ptrTo_a = *ptrToPtrTo_a;
delete ptrTo_a;

嘿,这个一模一样!括号唯一做的就是改变操作的顺序。您碰巧使用了“本机”顺序,所以括号什么也没做。

delete (A*)*a;

void* ptrTo_void = *a;
A*    ptrTo_a = (A*)ptrToVoid;
delete ptrTo_a;

这也行得通,只是走了一条不同的路。

哪一个是正确的?这确实是一种风格选择。我会给你我的风格经验法则:总是在不同的行上投射 void 指针。它使发生的事情更加清晰。

A* myObject = (A*)*a; // I prefer this one in this case, but what matters...
delete myObject;      // ... is that it is distinct from the delete...
*a = 0;               // ...not which cast is "best."

我喜欢这样做,因为当你真正开始着手时,我发现向/从 void 转换是一件非常棘手的事情。有很多地方可能会出错。我喜欢创建一个清晰的代码行,我可以在其中精神分裂我所有的演员,并确保它符合我的期望。因为我指定了我想要的变量的类型(myObjectA*,如果我搞砸了,编译器也无能为力),如果我做某事,我更有可能得到编译器错误错误的。从 void 编写强制转换非常容易,编译器会默默地进行您没想到的转换。然后,您将修复运行时错误而不是编译时错误。

我也喜欢使用该演员表作为放置 cmets 的好地方,以解释 为什么我认为首先进行演员表是安全的,例如“传递给的唯一 void 指针这个函数是我的函数在同一个 .cpp 文件中创建的函数,所以我确切地知道可以安全地转换为什么类型。”

【讨论】:

  • 谢谢!我是这么想的,但我的同学不同意,引用c-faq.com/ptrs/genericpp.html。我应该为此担心吗?关于“......依赖于具有相同内部表示的所有指针类型......”的部分
  • 嗯,这很有趣。在现实生活中的生产代码中我不会担心它(我不知道它会失败的单个编译器/平台),事实上我碰巧知道它是 COM 和 JNI 这两个主要标准中的基本操作。在课堂上,按照教授的指示去做。我认为,如果您想分叉,我更喜欢的版本可以解决 c-faq 中的问题,因此您可以安全地使用它。唯一有意义的平台是一种类型,例如doubles,存储在具有不同大小指针的完全不同的内存库中。
【解决方案2】:

delete ptr永远不会在 C 中编译。如果是,第一个选项将是正确的,而第二个选项将与它相同。

【讨论】:

  • 请改用free,与malloc 与其家族的其他功能相关。
  • @GingerPlusPlus:那是 UB;该对象由new 分配。阅读问题!
  • 1.它不会用 C 编译,它会被用 C 编译的代码调用。 2. 为什么前两个正确,最后一个不正确?
  • @Dori 对,好吧,这根本不是你的问题所说的。
  • 你是对的,但我确实尝试过编辑它。无论如何,问题2是我真正想知道的......
猜你喜欢
  • 2021-07-22
  • 2021-09-20
  • 2012-11-21
  • 2011-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-06
相关资源
最近更新 更多