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要多一些,通常是复制三个指针并将其归零,而不是复制一个指针。但与堆分配、向量复制等相比,这真的算不了什么。)