默认情况下,c++ 中的所有内容都是按值传递的

Everything in c++ by default is passed by value

本文关键字:按值传递 情况下 c++ 默认      更新时间:2023-10-16

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

例如,在 Java 中,默认情况下,将数组作为函数参数传递是通过引用传递的。C++能让你更好地控制这一点吗?

编辑:感谢您的所有回复,我想我更清楚地理解了整个按值传递的事情。对于任何仍然对Java如何通过值(对象引用的副本)传递感到困惑的人来说,这个答案确实为我澄清了它。

在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 *&),在这种情况下,现在指针确实是通过引用传递的 - 没有复制。

可能与您的问题无关,但我经常采取另一个方向来理解当您在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]视为"复制酒吧",如果我需要知道这样的副本是否是我想要的以及我需要的,我会直接去研究这门课,以了解该类通过复制特别意味着什么。