0

这段代码有什么潜在的危险吗?

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 会变为无效吗?有没有更好的方法来做到这一点,同时不制作不必要的向量副本?

4

2 回答 2

3

除了詹姆斯提供的答案之外,还有第三种可能性,与您的第一个想法具有相同的可读性,没有悬空引用,没有向量本身的堆分配,也没有不必要的副本:

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。

(对于挑剔者:是的,移动一个向量比传递一个引用要多一点,通常复制和归零三个指针而不是复制一个。但与堆分配、向量副本等相比,它真的没什么。)

于 2012-12-06T09:01:50.253 回答
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;
}
于 2012-12-06T02:55:38.477 回答