在函数内部创建局部向量,然后将其作为对其他函数的引用传递,这些函数将其存储为引用

时间:2012-12-06 02:49:47

标签: c++

此代码中是否存在潜在危险?

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。会不会变得无效?有没有更好的方法来做到这一点,而不是做不必要的矢量副本?

2 个答案:

答案 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;
}