为什么 std::vectors 不会作为数组从堆栈中销毁?

pep*_*320 4 c++ arrays vector

当我们这样使用数组和指针时:

int *g() {
  int arr[] = {1, 2, 3};
  return arr;
}

int f() {
  int *value = g();

  for (size_t i = 0; i < 3; i++) {
    std::cout << value[i] << " ";
  }
  std::cout << std::endl;
}

int main(int argc, const char **argv) {
  f();
  return 0;
}

Run Code Online (Sandbox Code Playgroud)

函数 g 返回后,它从堆栈中删除,因此我们在函数 f() 中得到段错误

但使用std::vector相同的逻辑没有任何问题:

std::vector<int> g() {
  std::vector<int> arr = {1, 2, 3};
  return arr;
}

int f() {
  std::vector<int> value = g();

  for (size_t i = 0; i < value.size(); i++) {
    std::cout << value.at(i) << " ";
  }
  std::cout << std::endl;
}

int main(int argc, const char **argv) {
  f();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我认为这与以下事实有关:我们将 std::vector 类充当数组的容器,但使用结构作为容器删除数组:

struct T {
  int *arr;
};

T g() {
  T t;
  int arr[] = {1, 2, 3};
  t.arr = arr;

  return t;
}

int f() {
  T value = g();

  for (size_t i = 0; i < 3; i++) {
    std::cout << value.arr[i] << " ";
  }
  std::cout << std::endl;
}

int main(int argc, const char **argv) {
  f();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,g++ 允许我们通过索引订阅来溢出数组指针内存限制。

为什么向量不存在同样的问题?

use*_*751 8

向量中的所有元素本质上都算作向量的一部分。请注意,您返回的是向量,而不是指向向量的指针。但是您正在返回一个指向数组(的开头)的指针。

当函数g返回时,向量arr被销毁,但这没关系,因为它与返回的向量不同。arr返回一份 的副本。(实际上,编译器足够聪明,可以重用相同的向量,而不是复制它然后删除一个向量 - 但你可以想象它会创建一个副本)

然后f从它自己的局部变量打印值value- 没问题。

相比之下,在指针版本中,正在打印内部f局部变量的值,该变量已经被销毁。如果返回一个指向向量的指针,也会有同样的问题。arrgg