将向量变量分配给自身是否会导致复制 C++

Dav*_*nan 1 c++ copy stdvector

假设我有一个向量:

std::vector<uint64_t> foo;
foo.push_back(1);
foo.push_back(27);
Run Code Online (Sandbox Code Playgroud)

我通过引用将该向量传递给函数。

calculate_something(foo);

int calculate_something(std::vector<uint64_t>& vec) {
  // ...
}
Run Code Online (Sandbox Code Playgroud)

在极少数情况下,函数需要本地修改向量,在这种情况下必须创建副本。这是正确的方法吗?

if (some_condition) {
  vec = vec;
}

vec.push_back(7);
Run Code Online (Sandbox Code Playgroud)

编辑:我自我分配的原因是因为分配给另一个变量会产生一个副本,我的直觉告诉我,当分配回同一个变量时,也会发生同样的情况。

use*_*522 10

不,这是不正确的。

C++ 中的赋值不会创建新对象或更改引用引用的对象。赋值仅更改左侧引用的对象的值(通过内置赋值运算符或通过operator=重载的常规行为)。

为了创建比表达式求值持续时间更长的新对象,您需要声明某个变量。这样的声明可以有一个初始化器,使用=它经常与赋值混淆,但事实并非如此:

std::vector<uint64_t> vec2 = vec;
Run Code Online (Sandbox Code Playgroud)

这将创建一个新vec2类型的对象std::vector<uint64_t>并使用 对其进行初始化vec,这意味着将vec其状态复制到vec2。这不是作业!如果你写的是

vec2 = vec;
Run Code Online (Sandbox Code Playgroud)

那么您可以进行赋值操作,将名为 的对象的状态修改vec2为等于 引用的对象的状态vec。但为了做到这一点,必须已经有一个声明,vec2其中已创建向量对象本身。分配不是创建一个新对象。

如果你只是使用

vec = vec;
Run Code Online (Sandbox Code Playgroud)

那么只有一个对象,即所vec引用的对象。是否允许这种赋值并不明显,但即使在最好的情况下,它所能做的就是将引用的对象的状态复制vec到引用的对象中vec,这意味着最后的状态vec应该简单地保持不变,并且没有其他副作用。

一般来说,您不能将 C++ 中的名称或引用重新绑定到新对象。

所以你想要的是

std::vector<uint64_t> local_vec = vec;
Run Code Online (Sandbox Code Playgroud)

然后您可以将local_vec其用作 的本地副本vecauto您可以通过使用来指示您希望变量具有与右侧相同的类型(减去引用和const限定符),从而避免指定类型:

auto local_vec = vec;
Run Code Online (Sandbox Code Playgroud)