我可以在超出范围后保留矢量数据吗

Can I keep vector data even after out of scope

我来自C背景。我曾经分配过memory/array,比如,把它发送到别的地方,指针就一直留在那里,即使之后,分配它的作用域也被销毁了。

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

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

... because a pointer to it is still saved it will still be kept?

没有!指向 std::vector 的指针或引用不会使向量保持活动状态。典型的错误示例是:

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

来自函数的 return 引用是悬空的。你不能用它做任何事。正确的方法是按值 return 并依赖 return 值优化:

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

如果你这样做:

auto y = foo();

不涉及复制,多亏了 NRVO。

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

std::vector 销毁时释放它所持有的内存。持有一个被销毁的对象的引用是非常糟糕的。访问它是 UB。一般规则:不要存储引用,仅在可以确定对象在整个范围内存在的地方使用它们,例如作为函数的参数。

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

如果您希望能够从不同位置访问数据,并且只要至少有一个位置仍然有一个 reference/pointer 就可以使用它,请不要使用 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

No if I do the same with vectors, I initialize a vector, pass it by reference, then keep the reference saved somewhere. After the initial method that actually created the vector goes out of scope, would it be destoryed?

是的。

or because a pointer to it is still saved it will still be kept?

没有


您可以像在 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 创建的任何内存。