此代码中是否存在潜在危险?
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。会不会变得无效?有没有更好的方法来做到这一点,而不是做不必要的矢量副本?
答案 0 :(得分:3)
除了James提供的答案之外,还有第三种可能性,与没有悬挂引用的第一个想法具有相同的可读性,没有载体本身的堆分配,也没有不必要的副本:
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
的移动广告被调用,这意味着它只占用vf
以前拥有的资源的所有权,所以没有不必要的副本和分配。 swap()
中的g()
仅在调用global
(以及g()
)之前存在f()
时才有效。您说要将向量存储在引用中,因此我假设g()
实际上创建了存储对象,并且在调用之前没有global
。然后,不应使用现有对象vg
进行交换,而应通过std::move
传递给存储对象。
总的来说,你实际上只创建了一个向量(vf
),其他所有向量都是相同的,move
d来自原始,所以你的性能与传递的基本相同参考,但没有悬挂参考。
(对于nitpickers:是的,移动向量比传递ref更多,通常复制和归零三个指针而不是复制一个。但是与堆分配,向量副本等相比,它实际上没什么。)
答案 1 :(得分:0)
是的,您描述的问题。在堆上创建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;
}