何时在游戏开发中使用C++指针

4

我看了很多文章,大部分都告诉我们同样的故事:除非必要,否则不要使用指针。作为一个来自C#/Java背景下熟悉内存管理的人,我完全不知道在什么情况下使用指针是适当的,除了以下这些情况:

  • 动态内存(例如变量大小数组)
  • 多态

在游戏开发的情况下,还有哪些情况下我会使用指针?


1
如果你是第一次用不熟悉的语言创建游戏,我不会担心指针的性能。 - luke
这不是关于性能的问题,但我不想从一开始就养成任何不良习惯,你知道我的意思吗? - jmegaffin
4
智能指针。智能指针无处不在。不使用它们是最糟糕的习惯之一。 - Collin Dauphinee
4个回答

7

“不要使用指针,它们很慢”在C++中没有意义。

这就像说,“不要使用变量,它们很慢”

  • 你是想说,“不要使用动态内存分配”吗?
    如果是这样的话:我认为你现在不用担心它。先编写代码,然后再进行优化。

  • 还是你想说,“不要使用裸指针(即类型为foo*的指针)”,这需要使用newdelete
    如果是这样的话,那是一个好建议:通常你需要智能指针来管理对象,而不是处理裸指针。在大多数C++代码中,您不应该需要使用newdelete,尽管这可能看起来很自然。
    但它们在幕后仍然是指针!

  • 还是你有其他意思?

附言

感谢下面的@bames53指出这一点:

如果传递副本是一个选项(即当您传递量的数据时,而不是一个大于几个寄存器的巨大结构或数组,例如在~16字节左右),请勿使用指针(或引用)来传递数据;改为通过复制传递。这样可以让编译器更好地进行优化。


2
我现在明白了。我只有在必要的时候才应该使用指针,并且我应该使用“智能指针”。 - jmegaffin
@bames53:你能提供示例代码来说明你的观点吗? - user541686
所以,shared_ptr基本上有一个垃圾回收器? - jmegaffin
编译器聪明并不能让问题消失。如果编译器无法利用严格别名规则,那么为了生成代码,它必须保守处理。也许有时编译器可以内联一个函数并进行一些分析以确定事情不会别名,但在生成具有外部链接的函数时,它无法执行该操作。维基百科文章链接到一些实际的代码。我没有其他东西可以给你运行在你自己的编译器上。 - bames53
1
它听起来像是内联做的任何事情都被禁用了,因为编译器本身无法证明当指针可以别名时这样做是安全的。因此,如果告诉它没有别名,优化就会启用。如果告诉它指针不别名,然后手动禁用优化,那么速度与以前一样慢。 - bames53
显示剩余12条评论

3

这个想法是你不希望出现内存泄漏,也不希望在检索内存时程序变慢,因此,如果预先分配所需的结构体,那么你可以使用指针来传递结构体,因为这样比复制结构体更快。

我认为你只是对为什么指针可能被认为是不好的感到困惑,因为有很多地方可以使用它们,你只需要考虑为什么要这样做。


那么我只有在无法使用引用或“常规”变量时才应该使用指针吗? - jmegaffin

3

指针的一个主要用途(虽然在可能的情况下,引用通常更好)是能够在不复制对象的情况下传递对象。如果一个对象包含大量数据,复制它可能会非常昂贵和不必要。在游戏开发方面,您可以将指针存储在像std::vector这样的容器中,以便您可以管理游戏中的对象。例如,您可以有一个向量,其中包含对游戏中所有敌人的指针,以便您可以对它们执行某些“大规模程序”。也许值得研究一下智能指针,因为这些可以使您的生活变得更加轻松(当涉及到防止内存泄漏时,它们非常有帮助)。


1

对于可变大小的数组,您不需要使用指针,通常应该使用std::vector。对于多态性,您也不需要使用原始指针;虚函数可以与智能指针(如unique_ptr)一起使用。

在现代C++中,您很少需要使用指针。通常它们会隐藏在资源拥有类(如向量)中。为了在不复制对象的情况下传递对象,您可以使用引用。大多数剩余的指针用途都由智能指针覆盖。非常少见的情况下,您可能需要一个“非所有权”指针,在这种情况下,原始指针是可以的。

如果您学习替代指针的内容,就会了解指针的适当用法。因此,请学习RAII、引用和智能指针。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接