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

C++ 在函数内创建局部向量,然后将其作为引用传递给其他函数,这些函数将其存储为引用,c++,C++,此代码中是否存在任何潜在危险 void f(){ std::vector<int> v; ... g(v); } void g(std::vector<int> &a){ ... //store a by reference in variable blah (global) } void f(){ std::向量v; ... g(v); } 空g(标准::向量&a){ …//将引用存储在变量blah(全局)中 } 当对f()

此代码中是否存在任何潜在危险

void f(){
    std::vector<int> v;
    ...
    g(v);
}

void g(std::vector<int> &a){
    ... //store a by reference in variable blah (global)
}
void f(){
std::向量v;
...
g(v);
}
空g(标准::向量&a){
…//将引用存储在变量blah(全局)中
}

当对f()的调用完成时,v将被销毁,但blah仍将引用v。废话会无效吗?有没有更好的方法来做到这一点,同时不制作不必要的向量副本

是的,这就是你所描述的问题。在堆上创建
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.
}
void f()
{
std::vector*v=新的std::vector();
// ...
g(v);
}
空g(标准::向量*a)
{
//胡说八道
//但别忘了删除它。
}
或者从一开始就将其作为一个全局

std::vector<int> v;

void f()
{
    g();
}

void g()
{
    // Use v;
}
std::vector v;
void f()
{
g();
}
void g()
{
//使用v;
}

是的,存在您描述的问题。在堆上创建
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.
}
void f()
{
std::vector*v=新的std::vector();
// ...
g(v);
}
空g(标准::向量*a)
{
//胡说八道
//但别忘了删除它。
}
或者从一开始就将其作为一个全局

std::vector<int> v;

void f()
{
    g();
}

void g()
{
    // Use v;
}
std::vector v;
void f()
{
g();
}
void g()
{
//使用v;
}

除了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);
}
std::向量全局//这里有些东西-你没有真正的全球化,是吗?
void f(){
std::向量vf;
/* ... */
g(std::move(vf));
}
void g(std::vector vg)//按值!
{
/* ... */
全球互换(vg);
}
由于您将
vf
“移出”
f()
vg
的move-ctor被调用,这意味着它只获得先前由
vf
拥有的资源的所有权,因此不会进行不必要的复制和分配。
g()
中的
swap()
仅在调用
g()
之前存在
global
时才有效(因此
f()
)。您说过要将向量存储在引用中,因此我假设
g()
实际上创建了存储对象,并且在调用之前没有
global
。然后,与其与现有对象交换,不如通过
std::move
vg
传递到存储对象

总的来说,您实际上只创建了一个向量(
vf
),所有其他向量实际上都是相同的,
从原始向量移动
d,因此您的性能基本上与通过引用传递相同,但没有悬空引用


(对于挑剔的人来说:是的,移动一个向量比传递一个ref要多一些,通常是复制三个指针并将其归零,而不是复制一个指针。但与堆分配、向量复制等相比,这真的算不了什么。)

除了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);
}
std::向量全局//这里有些东西-你没有真正的全球化,是吗?
void f(){
std::向量vf;
/* ... */
g(std::move(vf));
}
void g(std::vector vg)//按值!
{
/* ... */
全球互换(vg);
}
由于您将
vf
“移出”
f()
vg
的move-ctor被调用,这意味着它只获得先前由
vf
拥有的资源的所有权,因此不会进行不必要的复制和分配。
g()
中的
swap()
仅在调用
g()
之前存在
global
时才有效(因此
f()
)。您说过要将向量存储在引用中,因此我假设
g()
实际上创建了存储对象,并且在调用之前没有
global
。然后,与其与现有对象交换,不如通过
std::move
vg
传递到存储对象

总的来说,您实际上只创建了一个向量(
vf
),所有其他向量实际上都是相同的,
从原始向量移动
d,因此您的性能基本上与通过引用传递相同,但没有悬空引用

(对于挑剔的人来说:是的,移动一个向量比传递一个ref要多一些,通常是复制三个指针并将其归零,而不是复制一个指针。但与堆分配、向量复制等相比,这真的算不了什么。)