这段代码有什么潜在的危险吗?
void f(){
std::vector<int> v;
...
g(v);
}
void g(std::vector<int> &a){
... //store a by reference in variable blah (global)
}
对 f() 的调用完成后 v 被销毁,但 blah 仍将引用 v。 blah 会变为无效吗?有没有更好的方法来做到这一点,同时不制作不必要的向量副本?
这段代码有什么潜在的危险吗?
void f(){
std::vector<int> v;
...
g(v);
}
void g(std::vector<int> &a){
... //store a by reference in variable blah (global)
}
对 f() 的调用完成后 v 被销毁,但 blah 仍将引用 v。 blah 会变为无效吗?有没有更好的方法来做到这一点,同时不制作不必要的向量副本?
除了詹姆斯提供的答案之外,还有第三种可能性,与您的第一个想法具有相同的可读性,没有悬空引用,没有向量本身的堆分配,也没有不必要的副本:
std::vector<int> global; //somewehere - you don't have it really global, do you?
void f() {
std::vector<int> vf;
/* ... */
g(std::move(vf));
}
void g(std::vector<int> vg) //by value!
{
/* ... */
global.swap(vg);
}
由于您将vf
“移出” f()
,vg
因此调用了 move-ctor,这意味着它只获得了以前拥有的资源的所有权vf
,因此不会进行不必要的复制和分配。swap()
ing()
仅在global
调用g()
(因此f()
)之前存在时才有效。你说你想将向量存储在一个引用中,所以我假设g()
实际上创建了存储对象并且global
在调用之前没有。然后,与其交换现有对象,不如vg
将其传递std::move
给存储对象。
总的来说,您实际上只创建了一个向量 ( vf
),所有其他向量都与move
原始向量完全相同,因此您具有与通过引用传递基本相同的性能,但没有悬空的 ref。
(对于挑剔者:是的,移动一个向量比传递一个引用要多一点,通常复制和归零三个指针而不是复制一个。但与堆分配、向量副本等相比,它真的没什么。)
是的,有你描述的问题。要么v
在堆上创建
void f()
{
std::vector<int>* v = new std::vector<int>();
// ...
g(v);
}
void g(std::vector<int>* a)
{
// Store in blah
// But don't forget to delete it.
}
或者从一开始就将其作为一个全局对象。
std::vector<int> v;
void f()
{
g();
}
void g()
{
// Use v;
}