C++ 是不是通过值或引用传递对象?
Posted
技术标签:
【中文标题】C++ 是不是通过值或引用传递对象?【英文标题】:Does C++ pass objects by value or reference?C++ 是否通过值或引用传递对象? 【发布时间】:2014-02-08 12:36:34 【问题描述】:一个我在这里找不到答案的简单问题。
我的理解是,在调用期间将参数传递给函数时,例如
void myFunction(type myVariable)
void main()
myFunction(myVariable);
对于int
、float
等简单数据类型,函数按值调用。
但如果myVariable
是一个数组,则只传递起始地址(即使我们的函数是按值调用的函数)。
如果myVariable
是一个对象,也只传递对象的地址,而不是创建一个副本并传递它。
回到问题。 C++ 是通过引用还是值传递对象?
【问题讨论】:
@juanchopanza 书单?? :0 说真的,否决票??我必须买所有这些书才能知道问题的答案。对不起,我很难过 总的来说,这不是一个坏问题。但它确实表明,也许您应该坐下来了解一下该语言的基础知识,并通过一些测试用例进行试验。如果你这样做了,你会很快看到传递对象的默认行为是复制。你可以通过传递一个std::vector<int> myVariable
参数来看到这一点,在myFunction
中添加它并在那里打印,然后在main
中打印它。修改不会反映在main
的输出中。但是 C++ 可以超越这些约定。这是它的疯狂和魅力的一部分。阅读,不要绝望!
我的书没有阐明对象是如何传递的,以及数组传递。我很困惑。我用谷歌搜索和搜索here。所有问题都是具体的。没有找到一个普遍的答案,我决定问
Could we please be a bit nicer to new users?。他们在这里成群结队地狩猎。但不要担心它们。
我认为这是一个完全有效且有用的问题。我有几本关于 C++ 的书,并且已经断断续续地使用它 5 年了(主要用于学校作业),但我不总是记得我接触过的所有不同语言是如何在最低水平上运行的。在工作中,我在家里使用 C# 和一点 Python、C++ 来进行随机项目,上周我开始认真对待 C。他们的做法都有些不同,我需要一种快速简单的方法来刷新这个主题C++ 无需挖掘 400-600 多页的书籍。
【参考方案1】:
参数按值传递,除非函数签名另有说明:
在void foo(type arg)
中,无论type
是简单类型、指针类型还是类类型,arg
都是按值传递的,
在void foo(type& arg)
中,arg
是通过引用传递的。
对于数组,传递的值是指向数组第一个元素的指针。如果您在编译时知道数组的大小,也可以通过引用传递数组:void foo(type (&arg)[10])
。
【讨论】:
我认为我们在谈论这个问题时应该谨慎对待条款。传值表示“你得到的是参数的值”,而传值表示“你得到的是参数的引用/别名”,分别独立编译器真正做了什么(复制、移动、删除副本、传递指针、传递引用等)。我发表了这条评论,因为我认为用 copy 识别 pass by value 和 pass by reference 用 no copy 是误解的常见来源,从 C(没有通过引用传递,用指针模拟它)、C++ 和 Java 开始。 @Manu343726 C 没有通过引用。如何?如果通过引用传递意味着传递地址,那么C如何没有通过引用传递?我认为按引用传递与 REFERENCE VARIABLES 无关,但它与通过指针或引用变量传递地址有关。 @aLearner 通过引用传递意味着为现有对象创建别名。因此,当您使用“int & a = x”时,您正在为 x 创建新名称。这样做的主要原因是在修改 a 时更改 x 的值。在 C 中,无法为相同的现有对象添加新名称,因此我们获取对象的地址并传递它,以便我们可以更改原始变量的值。使用指针,您实际上是在使用按值复制。当您使用“int * a = &x”时,您正在复制地址的值。这就是 Manu343726 使用指针模拟引用的意思。【参考方案2】:C++ 总是为您提供选择:所有 类型 T
(数组除外,见下文)可以通过将参数类型设为 T
按值传递,并通过将参数类型设为参数类型T &
,引用-T
。
当参数类型未显式注释为引用 (type &myVariable
) 时,无论具体类型如何,它总是按值传递。也适用于用户定义的类型(这就是复制构造函数的用途)。同样对于指针,即使复制指针不会复制指向的内容。
数组有点复杂。数组不能按值传递,像int arr[]
这样的参数 类型实际上只是int *arr
的不同语法。这不是传递给从数组中生成指针的函数的行为,实际上是所有可能的操作(不包括像sizeof
这样的少数操作)does that。一个可以传递一个对数组的引用,但这明确注释为引用:int (&myArray)[100]
(注意与符号)。
【讨论】:
+1 指出int arr[]
实际上只是 int *arr
。这清楚地说明了为什么按值传递数组似乎与其他类型 T 的工作方式不同,因为实际上,如果您改为编写 int *arr
,它的工作方式正是您所期望的。【参考方案3】:
C++ 使按值传递和按引用传递两种范式成为可能。
您可以在下面找到两个示例用法。
http://www.learncpp.com/cpp-tutorial/72-passing-arguments-by-value/
http://www.learncpp.com/cpp-tutorial/73-passing-arguments-by-reference/
数组是特殊的结构,当您将数组作为参数传递时,指向第一个元素地址的指针作为值传递给数组中元素的类型。
当你将指针作为参数传递时,实际上你自己实现了引用传递范式,就像在 C 中一样。因为当你修改指定地址中的数据时,你正是修改了调用者函数中的对象。
【讨论】:
【参考方案4】:在 C++ 中,声明为类、结构或联合的类型被视为“类类型”。这些是按值传递的,或者您可以说使用复制构造函数的副本传递给函数。当我们实现二叉树时,这一点非常明显,其中在递归函数中几乎总是有一个 Node * 类型的参数作用于二叉树。这是为了便于修改该节点。如果节点按原样传递(即不是指针类型),则对节点的修改将是本地副本。即使在向量的情况下,在传递向量的副本时也会将其传递给函数,以避免我们使用引用 &。
【讨论】:
【参考方案5】:C++ 按值传递非指针 (int*) 或引用 (int&) 的参数。您不能在被调用函数中修改调用块的 var。数组是指针。
【讨论】:
C++ 也通过值传递指针。没有神奇的例外。 在 C++ 术语中,参数类型是指针这一事实不会影响它是按值还是按引用。如果它只是一个指针,它是按值。如果是对指针的引用,则为引用。 我的意思是,参数被声明为指针或引用。对不起,我的英语不好。我从“我可以在被调用的函数中修改传递的变量”的意义上理解这个问题。 如果参数声明为指针,则指针按值传递。如果它被声明为对指针的引用,它是通过引用传递的。此外,数组不是指针。 juanchopanza - 数组退化为指针。例如,请参阅***.com/questions/4223617/…。以上是关于C++ 是不是通过值或引用传递对象?的主要内容,如果未能解决你的问题,请参考以下文章