【问题标题】:Are vectors passed to functions by value or by reference in C++在 C++ 中,向量是按值传递还是通过引用传递给函数
【发布时间】:2014-12-26 03:34:43
【问题描述】:

我正在用 C++ 编写代码。如果我有一些函数void foo(vector<int> test) 并在我的程序中调用它,那么向量是按值传递还是按引用传递?我不确定,因为我知道向量和数组是相似的,并且像 void bar(int test[]) 这样的函数会通过引用(指针?)而不是值来传递测试。我的猜测是,如果我想避免按值传递,我需要通过指针/引用显式传递向量,但我不确定。

【问题讨论】:

  • C++ 有“按值传递”的语义,所以是按值传递的。不过,您可以决定通过引用传递。选择实际上取决于函数的作用。
  • 通过引用使用,如果您不希望函数更改矢量内容使其成为 const,否则只需通过引用传递它。它将避免不需要的和昂贵的(有时)复制
  • 另外,引用不是指针。
  • @AliKazmi 除非你想在函数体中复制。
  • 这取决于你想要达到的目标。有时使用标准智能指针之一很有用,例如,如果您想传递所有权,则使用 unique_ptr。但通常,我通过引用传递 std::vector。

标签: c++ arrays vector


【解决方案1】:

在 C++ 中,除非您另外指定使用 &-操作符(请注意,此操作符也用作“地址”操作符,但在不同的上下文中),否则事物是按值传递的。这都是有据可查的,但我还是会重复一遍:

void foo(vector<int> bar); // by value
void foo(vector<int> &bar); // by reference (non-const, so modifiable inside foo)
void foo(vector<int> const &bar); // by const-reference

您也可以选择将指针传递给向量 (void foo(vector&lt;int&gt; *bar)),但除非您知道自己在做什么并且觉得这确实是可行的方法,否则不要这样做。

此外,向量与数组相同!在内部,向量会跟踪它为您处理内存管理的数组,但许多其他 STL 容器也是如此。您不能将向量传递给需要指针或数组的函数,反之亦然(您可以访问(指向)底层数组并使用它)。向量是通过其成员函数提供许多功能的类,而指针和数组是内置类型。此外,向量是动态分配的(这意味着大小可以在运行时确定和更改),而 C 样式的数组是静态分配的(其大小是恒定的,必须在编译时知道),限制了它们的使用。

我建议您阅读更多有关 C++ 的一般信息(特别是 array decay),然后查看以下程序,该程序说明了数组和指针之间的区别:

void foo1(int *arr) { cout << sizeof(arr) << '\n'; }
void foo2(int arr[]) { cout << sizeof(arr) << '\n'; }
void foo3(int arr[10]) { cout << sizeof(arr) << '\n'; }
void foo4(int (&arr)[10]) { cout << sizeof(arr) << '\n'; }

int main()
{
    int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    foo1(arr);
    foo2(arr);
    foo3(arr);
    foo4(arr);
}

【讨论】:

  • 谁能帮我理解最后一个声明 foo4 函数?为什么它像其他函数一样返回数组的大小而不是指针的大小?
  • @abhishek_M 因为参数类型是引用。引用只能绑定到完全相同类型的表达式。由于这个原因,数组不会衰减,因为对数组的引用不能绑定到指针,它只能绑定到相同类型的数组(在本例中为 10 个整数的数组)
  • c++11 具有“移动语义”,您可以谨慎执行并按值传递(使用移动语义)而无需复制。这是一个对我有很大帮助的链接:mbevin.wordpress.com/2012/11/20/move-semantics
  • 从语言设计的角度来看,foo3 行为背后的目的/想法是什么?当数组的大小在编译时已知时,为什么在这种情况下需要衰减?
【解决方案2】:

vector 在功能上与数组相同。但是,对于语言来说,vector 是一种类型,int 也是一种类型。对于函数参数,任何类型的数组(包括vector[])都被视为指针。 vector&lt;int&gt;int[] 不同(对于编译器)。 vector&lt;int&gt; 是非数组、非引用和非指针 - 它是按值传递的,因此它将调用复制构造函数。

因此,您必须使用vector&lt;int&gt;&amp;(如果函数没有修改它,最好使用const)将其作为引用传递。

【讨论】:

  • 通过引用函数传递“向量数组”的语法是什么?
  • void functionName(std::vector (&vc)[5]){}
【解决方案3】:

void foo(vector&lt;int&gt; test)

vector 将在 this 中按值传递。

你有更多的方法来传递向量,具体取决于上下文:-

1) 通过引用传递:- 这将使函数 foo 更改向量的内容。由于避免了向量的复制,比按值传递更有效。

2) 通过 const-reference 传递:- 当您不希望函数更改向量的内容时,这既高效又可靠。

【讨论】:

    【解决方案4】:

    当我们在函数中按值传递向量作为参数时,它只是创建向量的副本,并且当我们调用该特定函数时,主函数中定义的向量不会发生任何影响。 而当我们通过引用传递向量时,该特定函数中写入的任何内容, 当我们调用特定函数时,每个动作都将在 main 或其他函数中定义的向量上执行。

    【讨论】:

      猜你喜欢
      • 2020-04-01
      • 2014-04-08
      • 1970-01-01
      • 2010-09-05
      • 2016-06-11
      相关资源
      最近更新 更多