【问题标题】:Everything in c++ by default is passed by value默认情况下,c++ 中的所有内容都是按值传递的
【发布时间】:2016-06-01 09:53:27
【问题描述】:

在 C++ 中,是否所有类型都按值传递,除非它带有 &* 符号?

例如,在 Java 中,将数组作为函数参数传递将默认通过引用传递。 C++ 是否让您对此有更多控制权?

编辑:感谢您的所有回复,我想我更清楚地了解整个传递值的事情。对于仍然对 Java 如何按值传递(对象引用的副本)感到困惑的任何人,this answer really cleared it up for me.

【问题讨论】:

  • 即使在java中,对象也是按值传递的。理想情况下,将对象视为通过引用传递会使它更容易理解,这可能是一些书籍和参考文献将传递对象称为pass by reference 的原因。 Java 遵循按值传递,其中没有像 pass by reference 这样的东西。
  • 在传递数组的情况下,C++ 提供了向量作为另一种选择。我只是把这句话放在了错误的地方,对所有的反对者。
  • 在比较两种语言以及它们如何处理参数时,我会避免使用“价值”和“参考”之类的术语。 C++ 的这些术语意味着特定的东西。 Java 的这些术语意味着特定的事物。对于另一种语言,再次,具体的事情。
  • 在Java中,“引用”是一种值,用于引用这些值的“引用”一词与“通过引用传递”无关。 “按引用传递”和“按值传递”是指函数传递的是对变量的引用还是变量的值。
  • 请注意,C++11 添加了&&

标签: c++ pass-by-reference pass-by-value


【解决方案1】:

在 C++ 中,所有类型都是按值传递的,除非它带有 & 或 * 符号?

不,如果您将某些东西作为 * 参数(其指针)传递,它仍然由 传递。制作了正在传递的指针的副本。但原件和副本都指向同一个内存。它在 C# 中是类似的概念——我也相信在 Java 中,只是你不在那里使用 *。

这就是为什么如果您使用此指针对外部对象进行更改(例如使用解引用),更改也会在原始对象中可见。

但是如果你只是说给指针分配一个新值,外部对象不会发生任何事情。例如

void foo(int* ptr)
{
  // ...
  // Below, nothing happens to original object to which ptr was 
  // pointing, before function call, just ptr - the copy of original pointer - 
  // now points to a different object 
  ptr = &someObj; 
  // ...
}

例如在 Java 中,将数组作为函数参数传递将是 默认通过引用传递。 C++ 是否给你更多的控制权 这个?

在 C++ 或 C 中,如果您传递数组(例如 int arr[]),传递的内容将被视为指向数组第一个元素的指针。因此,我上面所说的在这种情况下也适用。

关于&你是对的。您甚至可以将 & 应用于指针(例如,int *&),在这种情况下,指针确实通过引用传递 - 没有复制。

【讨论】:

  • actually what is being passed is treated as pointer 这也适用于 java。 Java 也没有像引用传递这样的东西。
  • @MathewsMathai 我正在修改,你可以交叉检查
  • 好吧,我刚刚提到。没有冒犯。
  • 别忘了在 C++ 中实际上可以通过引用传递数组。
【解决方案2】:

可能与您的问题无关,但我经常采取另一个方向来理解当您在 C++ 中调用函数时会发生什么。

两者的区别

void foo(Bar bar);  // [1]
void foo(Bar& bar); // [2]
void foo(Bar* bar); // [3]

[1] 中的正文将收到原始条的副本(我们将其称为按值,但我更愿意将其视为我自己的副本)。

[2] 的主体将使用完全相同的 bar 对象;没有副本。我们是否可以修改bar 对象取决于参数是Bar& bar(如图所示)还是const Bar& bar。请注意,在格式良好的程序中,[2] 将始终接收一个对象(没有 null 引用;让我们将悬空引用放在一边)。

[3] 的主体将收到指向原始bar 的指针的副本。我是否可以修改指针和/或指向的对象取决于参数是const Bar* barconst Bar* const barBar* const bar 还是Bar* bar(是的,真的)。指针可能是也可能不是null

我做出这种心理区分的原因是因为对象的副本可能有也可能没有引用语义。例如:此类实例的副本:

struct Foo {
 std::shared_ptr<FooImpl> m_pimpl; 
};

默认情况下,将具有与原始内容相同的“内容”(指向相同FooImpl 指针的新共享指针)。当然,这取决于程序员是如何设计类的。

出于这个原因,我更喜欢将[1] 视为“复制吧”,如果我需要知道这样的副本是否是我想要的以及我需要什么,我会直接去学习课程以了解copy 中的那个类具体是什么意思。

【讨论】:

    猜你喜欢
    • 2020-09-08
    • 2011-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-22
    • 1970-01-01
    • 2013-09-01
    • 2017-12-16
    相关资源
    最近更新 更多