如果我从一个函数返回一个向量,则为其分配了对象的地址将与该函数中声明的地址具有相同的地址(不将其作为引用返回)。例如:
vector<int> f() {
vector<int> foo(5);
cout << &foo << endl;
return foo;
}
int main() {
vector<int> bar = f();
cout << &bar << endl; // == &foo
return 0;
}
然后,我认为这是由于复制构造函数而发生的,并且&运算符可能会以某种方式重载,从而打印出从foo复制到bar的向量类的特定成员的地址。 但是,如果我更改场景并在类中移动f(),则行为将与我最初预期的一样:&foo!=&bar:
class A {
vector<int> foo;
public:
vector<int> f() {
foo.push_back(10);
cout << &foo << endl;
return foo;
}
};
int main() {
A a;
vector<int> bar = a.f();
cout << &bar << endl; // != &foo
return 0;
}
你能解释会发生什么吗?
答案 0 :(得分:2)
向量的地址代表什么?
计算机内存可以是字节数组。内存地址是该图形阵列的索引。所有对象(包括矢量)都是相同的。
如果我从一个函数返回一个向量,则为其分配了对象的地址将与该函数中声明的地址具有相同的地址(不将其作为引用返回)。
这不是标准所保证的。但是确实有可能。每当使用命名的返回值优化来取消返回值的复制/移动时,都会发生这种情况。
然后我认为这是由于...&运算符可能以....
vector运算符的地址未重载。
你能解释会发生什么吗?
您返回成员的副本,而不是本地自动变量。在这种情况下,不能使用NRVO。
不管子对象如何,在任何给定时间都不能有多个对象与同一内存重叠。如果两个对象同时存在,则每个对象必须具有不同的地址。另一方面,一旦释放了一个对象的内存,它就可以被另一个对象重用。
在第一个示例中,局部变量的生存期结束,因此它的内存与从返回值初始化的变量的内存重叠没有问题。
在第二个示例中,a
的生存期以及因此其成员与bar
的生存期重叠,因此它们在内存中不能重叠。