你啥时候想在 C++ 中使用指针和值?

Posted

技术标签:

【中文标题】你啥时候想在 C++ 中使用指针和值?【英文标题】:When do you want to use pointers vs values in C++?你什么时候想在 C++ 中使用指针和值? 【发布时间】:2010-12-06 12:28:48 【问题描述】:

我来自 Java,正在尝试学习 C++。

据我所知,使用指针与 Java 中引用变量的工作方式非常相似,因为您将内存地址传递给值。所以我觉得我对他们有了很好的了解。我也明白这些变量是存储在堆上的。

但是,我发现还有另一种方法可以在 C++ 中声明变量,而无需 new 运算符/指针简单地执行以下操作:

Employee boss("Frank");

这将创建一个以“Frank”为参数的 Employee 值。这些变量存储在堆栈中。

所以,您有这两种非常不同的创建变量的方式,并且都有自己独特的行为(还有内存管理?)。

我的问题是,什么时候适合使用指针 VS 值?最佳做法是什么?我应该如何知道大多数时候我想以哪种方式声明我的变量?

【问题讨论】:

“参考”是 C++ 中的一个特定术语,所以我稍微编辑了您的问题以使用更正确的“值”。 @John Millikin,感谢您清理我的帖子,您的意图是正确的。我有时仍然会偶然发现 C++ 命名法。 我建议在学习 C++ 之前先忘掉 Java。它们是不同的,如果你试图在它们之间进行类比,你只会混淆你自己和我。 复制,无论如何:***.com/questions/1064325/…. @GMan,我对它们进行了比较,因为我发现指针类似于 Java 的参考变量。然后我说我理解 2 种 C++ 变量创建方法背后的行为,我想回答的唯一问题是何时适合使用特定的方法。 【参考方案1】:

C++ 指针的操作与 Java 对象完全一样,因为它们可能无效 (NULL) 并且传递给过程的成本很低。

C++ 引用是指针的薄包装。它们不应该是无效的,但在某些情况下可能是。例如,引用可能是从 NULL 指针创建的,或者它引用的内存可能会被删除。

在你给出的代码示例中:

Employee boss("Frank");

你正在使用一种叫做“价值”的东西。与指针和引用不同,值它们所代表的对象,而不是间接。

我的问题是,什么时候合适 使用指针 VS [值]? 最佳做法是什么?应该怎样 我知道我想以什么方式声明 大部分时间都是我的变量?

C++ 没有垃圾收集,因此当变量的范围有限时使用值。例如,您可以在堆栈上分配它们,而不用担心内存,而不是用new 分配一个并用delete 解除分配过程中的每个变量。

【讨论】:

【参考方案2】:

这里有两个不同的问题:创建对象和引用它们。

创作

创建对象的地方有两个:栈和堆。如果您使用您描述的语法:

Employee boss("Frank");

将在堆栈上创建它。如果你这样写:

Employee* boss = new Employee("Frank");

它将在堆上创建它。如果您不熟悉堆栈和堆的概念,那么成为一名优秀的 C++ 编码员至关重要,因此请了解它!

参考

引用对象有些不同。无论对象是如何创建的,都可以使用指针或引用(或仅标准变量)来引用它。在 C/C++ 中使用引用和指针实际上是一回事,尽管有一些重要的区别。

当使用指针或引用时,对象的副本不会制作。

// No copies made:
Employee& frank = boss;  // Using References
Employee* frank = &boss; // Using a Pointer

两者都不使用时会生成一个副本。

// Copy is made:
Employee frank = boss;

那么什么时候使用指针,什么时候使用引用呢?我发现一个好的做法是仅在对 null 有意义时才使用指针。如果某些内容不应该为空,请将其设为引用。

【讨论】:

【参考方案3】:

通常,您希望尽可能多地使用参考文献。原因是因为RAII。基本上,如果您使用 RAII,这可以保证没有内存泄漏。

但是,当您使用的对象复制起来非常昂贵时,IMO 您应该使用指针。传递容器类型会导致容器重复...不是一个好主意。

最好的方法是使用smart pointers... 基本上是持有一个指针并跟踪指针的引用数量的引用。这确实是两全其美...廉价的初始化/复制和引用计数实际上消除了内存泄漏。

【讨论】:

【参考方案4】:

注意:我将使用“object”来指代对象和原始类型,例如 int、float……这些在 C++ 中是不一样的(但通常你可以忽略它)。

在您创建从该范围控制的对象时使用值,并且在该范围结束时它应该死掉。此外,当您想使用外部对象的副本时使用 value,但您只想处理副本而不是真实对象。示例:

int myFunction(int external_value1, Object external_value2)
    ---

当你创建一个在创建范围结束时不应该死掉的对象时使用指针/引用(确保将指向它的指针传递到其他范围!),或者当使用复制成本高昂的外部值时(像一个容器),或者当你想直接操作那个外部对象而不是它的副本时。这就是为什么函数的 I/O 参数通常是指针或引用的原因,因为您希望直接作用于外部对象(在函数范围之外定义)而不是本地副本。示例:

int myOtherFunction(int *external_value1, Object *external_value2
    ---

在这个例子中,如果你对参数指向的值进行操作,你会影响到:那些指针指向的值,从而改变函数范围之外的变量。实际上是按值传递,但您只是复制指针,并使用它们“攻击”外部值。

正如其他帖子所述,引用只是指针的语法糖。一旦你理解了指针,你就理解了引用;)。

【讨论】:

【参考方案5】:

C++ FAQ 对这个特定问题有很好的回答:

http://www.parashift.com/c++-faq-lite/references.html#faq-8.6

【讨论】:

不是真的;他在 Java 方面的背景引起了一些术语混乱。他不是在问指针与引用,而是指针与堆栈分配的值。【参考方案6】: When to use pointers and when not to? C++ References and Java References Switching from Java to C++ - What's the Easy Way? many more

【讨论】:

【参考方案7】:

两种不同的野兽:如果你通过指针分配,你最终会得到 n 对 1 的关系,你必须通过适当的资源管理来处理。这通常在 Java 中处理。

在所谓的“参考对象”中,您会得到不同的对象(需要跟踪等)。

【讨论】:

你怎么称呼“参考对象”,所以我知道正确的术语吗?我不知道所以我只是编造了一些东西。

以上是关于你啥时候想在 C++ 中使用指针和值?的主要内容,如果未能解决你的问题,请参考以下文章

C++ 将指针传递给函数 (Howto) + C++ 指针操作

指向成员函数的 C++ 指针

在 C++ 中何时使用指针? [复制]

用指针传递引用和值[重复]

C++ 野指针规避指南!

将 numpy 指针 (dtype=np.bool) 传递给 C++