C++ 从函数返回ref到数据会导致悬空ref问题
请检查下面的两个代码段。在示例2中,当传递局部变量的ref时,显然存在悬而未决的引用问题,您认为示例1中存在相同的问题吗?我自己认为样本1是正确的。在数据结构(C++ 从函数返回ref到数据会导致悬空ref问题,c++,reference,dangling-pointer,C++,Reference,Dangling Pointer,请检查下面的两个代码段。在示例2中,当传递局部变量的ref时,显然存在悬而未决的引用问题,您认为示例1中存在相同的问题吗?我自己认为样本1是正确的。在数据结构(stl::queue)中推送数据时,采用了ref(函数头enqueue为void enqueue(const int&data))。因此,通过此处的&data返回数据时应该不会出现问题。还是有 样本1: int const& dequeue() { _mutex.lock(); int &data = _q
stl::queue
)中推送数据时,采用了ref(函数头enqueue
为void enqueue(const int&data)
)。因此,通过此处的&data
返回数据时应该不会出现问题。还是有
样本1:
int const& dequeue()
{
_mutex.lock();
int &data = _queue.back();
_queue.pop();
_mutex.unlock();
return data;
}
样本2:
int const& dequeue()
{
_mutex.lock();
int data = _queue.back();
_queue.pop();
_mutex.unlock();
return data;
}
示例1不正确
一旦调用pop()
,您的引用将无效
函数将返回的引用必须是在函数终止时仍然有效的对象
这也意味着示例2不正确,但不是因为您认为的原因。是的,返回该引用是无效的(它甚至不应该编译),但在函数结束之前,数据
是无效的-同样,在调用pop()
之后,对该容器中对象的任何引用都将无效
你有什么理由通过推荐信返回吗?显然,您根本不希望值发生更改,而且您的引用是const
,所以为什么不直接按值返回呢
int dequeue()
{
_mutex.lock();
int data = _queue.back();
_queue.pop();
_mutex.unlock();
return data;
}
在回答您更一般的问题时,关于返回本地声明的引用,只要它引用的对象在函数终止后仍然有效,就可以了。例如:
int glob;
int& f(){
int x;
int& ref = glob;
return x;
}
int main(){
foo()=10; //this is fine
}
示例2肯定已损坏,您通过引用返回一个临时值。对于示例1,请澄清,
pop()
是否删除通过back()
获得的项目?在这种情况下,数据
也将成为一个无效的引用。@Kerrek,我认为这不是问题的重点,但一些澄清还是不错的-如果问题是因为代码不起作用而提出的,这可能就是原因。我选中:pop()
删除了使用front()
访问的最旧元素。因此,如果您的队列只有一个元素,那么您将得到一个无效的引用。否则,你的命运未定;其他线程可能会弹出您的队列,直到它变得无效。stl::queue.pop()将删除该项。Kerrek的观点是,您正在分配back
元素,而弹出front
元素。例如,q={1,2};i=q.back(),q.pop()
然后q=={2},i==2
您的示例很好,但是如果您适当地修改容器,对容器成员的引用不是变得无效吗?例如,set v{2,7,5,12};int&a=*v.begin();v、 清除()代码>--现在写入a
是不好的,不是吗?@Dominic:但是a
与任何迭代器有什么关系呢?我取消了对begin()
的引用,因此获得了对容器中某个元素的引用。在一个向量中,我可以写int&a=v[3]代码>相同的想法(只是在向量中,在clear()
之后,内存可能仍然有效)a
只是一个int引用。排队的情况不是一样吗?(假设back()
返回一个引用。)哦,我明白你的意思了。是-我想说pop()
使任何迭代器和引用无效。而且back()
确实返回了一个引用。@丹尼斯:差不多了。他弹出“底部”元素,如果这是您描述队列的方式。但这仍然是鲁莽的,因为他不是唯一一个访问队列的人,最终该引用可能会变得无效。@Faisal:指针将给出与引用完全相同的问题。任何对元素(包括指针)的直接引用都可能因修改而无效。基本上,如果您的函数修改了容器,并且希望返回容器的元素,那么按值返回是唯一安全的选项。