即使在超出范围之后,我是否可以保留矢量数据

Can I keep vector data even after out of scope

本文关键字:是否 保留 数据 之后 范围      更新时间:2023-10-16

我来自C背景。我曾经分配内存/数组,例如,将其发送到其他地方,指针留在那里,即使在分配它的范围被破坏之后。

现在,如果我对向量做同样的事情:初始化,通过引用传递它,然后将该引用保存在某个地方。在实际创建向量的初始方法超出范围之后,它会被销毁吗?或者,由于指向它的指针仍然保存,它将被保留。

std::vector

在销毁时释放它所拥有的内存。保留对被破坏的对象的引用是非常糟糕的。访问它是 UB。一般规则:不要存储引用,只在可以确定对象在整个范围内存在的情况下使用它们,例如作为函数的参数。

如果要保留数据的副本,只需复制std::vector即可。无需参考。

如果您希望能够从不同位置访问数据,并且只要至少一个位置仍有指向它的引用/指针,就让它保持存在,请不要使用std::vector,使用std::shared_ptr

如果您想将std::vector的好处与共享内存的好处结合起来,共享内存一直存在到最后一个地方放手,请将它们结合起来:std::shared_ptr<std::vector<...>>.

如果要让std::vector在一个地方居住一会儿,然后在另一个地方居住,但不再首先居住,请使用移动语义

std::vector<int> foo = {1, 2, 3};
std::vector<int> bar = std::move(foo); // bar now holds the data that foo held, foo is empty, no copy was performed

指向堆栈上数组的指针不会使数组保持活动状态,我想在 C 中也是如此。现在向量不是数组。它是堆分配数组的包装器,当数组超出范围时,它会释放数组的内存。

。因为指向它的指针仍然保存,它仍然会被保留吗?

不!指向std::vector的指针或引用不会使矢量保持活动状态。规范错误的例子是:

std::vector<T>& foo() {
std::vector<T> x;
return x;
}                      // baaam !

从函数返回的引用悬而未决。你对它无能为力。正确的方法是按值返回并依赖于返回值优化:

std::vector<T> foo() {
std::vector<T> x;
return x;
}

如果您这样做:

auto y = foo();

由于 NRVO,不涉及复制。

PS:编译器应该警告您返回对局部变量的引用。

不,如果我对向量做同样的事情,我初始化一个向量,通过引用传递它,然后将引用保存在某个地方。在实际创建向量的初始方法超出范围后,它会被取消吗?

是的。

还是因为指向它的指针仍然保存,它仍然会被保留?

不。


您可以在C++中悬挂指针,就像在 C 中一样。这是完全一样的。

引用通常也是如此(尽管在某些情况下,对象的生存期会延长一点(。

的确,向量的数据由向量在内部管理,但这是顺便的,因为您是在询问向量本身。忘记向量并问关于int的相同问题,然后你会意识到答案就像你期望的那样在 C 中。

现有的答案很好,将在此处添加:

block A
{
vector<int> my_vec(10, 0);
//...something...
}
block B

my_vec矢量将超出范围并在右括号处销毁。 现在是 stl(标准模板库(向量。

您还可以使用 C 样式数组(但语法不同(。 对于非常大的数组,我发现动态分配数组的分配时间比 STL 向量快。

//static, goes out of scope and memory handled at the end of code block
int arr0[10];
//dynamic, not destroyed unless delete called.
int* arr1 = new int[10];
//...work with arr1...
delete [] arr1;

就像在 C 中一样,您需要注意取消分配使用new创建的任何内存。