当我使用字符串作为方法的参数时,函数中字符串的更改不会反映在调用函数中。简单的理由按价值传递。
但是当使用向量时,对向量的更改会在调用函数中反映出来。所以我的问题是传递向量就像是通过引用调用,我们在内存中发送地址而不是变量,因此函数内的任何更改都会反映在调用函数中
------------------------更新---------------------- ----------
所以向量必须仅通过引用传递?我不能正常做到这一点?
当然你可以正常传递它们(通过值传递它们)。但是当你按值传递对象时,会发生一个新对象,然后将传递的对象复制到新对象。这对于标准类型(char,int,float等)是可以的,因为标准类型的大小很小(char是一个字节,short是2,int是2或4,long是4等等)。然而,矢量并不小。试着这样做:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v;
cout << sizeof(v) << endl;
system("pause");
return 0;
}
在我的电脑中我得到12作为输出。这是12个字节。因此,我不是通过值传递,而是通过引用传递它,其成本为4个字节(包含向量地址的变量的大小)
答案 0 :(得分:5)
但是当使用向量时,对向量的更改会反映在调用函数中。
这是因为通过引用传递。如果您通过引用传递std::string
,您将获得相同的效果。
反之亦然:如果省略参数声明中的&符号,则可以按值传递std::vector
。但是,这可能会带来很高的成本,因为矢量的整个内容都将被复制。
所以向量必须仅通过引用传递?
它们不必通过引用传递,但在许多情况下,通过值传递过于昂贵,因此人们很少这样做。就sizeof(v)
而言,只能获得与向量对象本身一起分配的向量的小占用空间(在这种情况下,它位于堆栈中)。向量内部的指针也指向动态部分,而sizeof
运算符不考虑这一部分。
答案 1 :(得分:1)
我想花点时间指出String是一个特例。 String是一个final类,这意味着它是不可变的,不能被修改。
答案 2 :(得分:1)
假设这确实是一个Java问题:
String
和Vector
类型都按值传递(但传递的值实际上是引用)。考虑:
void foo1 (String s) {
s = new String("abcde");
}
void foo2 (Vector<Integer> v) {
v = new Vector<Integer> ();
}
在中,情况都不会影响来电者的参数。这两个都将修改传递的对象引用的本地副本,但不会对引用的对象执行任何操作。
如果你做了修改矢量的事情,那么:
void foo3 (Vector<Integer> v) {
v.add (10);
}
这会修改v
指向的对象。如果有一个方法修改了String
,就像这样:
void foo4 (String s) {
s.setChar(0, '!'); // does not exist in Java
// but pretend that it changes the first character of the string
}
那么这也会修改调用者传递给foo4
的对象。但我无法给出一个真实的例子,因为String
对象在Java中是不可变的。