Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从函数返回ref到数据会导致悬空ref问题_C++_Reference_Dangling Pointer - Fatal编程技术网

C++ 从函数返回ref到数据会导致悬空ref问题

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

请检查下面的两个代码段。在示例2中,当传递局部变量的ref时,显然存在悬而未决的引用问题,您认为示例1中存在相同的问题吗?我自己认为样本1是正确的。在数据结构(
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:指针将给出与引用完全相同的问题。任何对元素(包括指针)的直接引用都可能因修改而无效。基本上,如果您的函数修改了容器,并且希望返回容器的元素,那么按值返回是唯一安全的选项。