微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 将非左值作为const引用参数传递. temp是在本地范围还是调用范围内创建的?

好吧,所以,我已经知道,当我们尝试使用它时,返回一个局部变量作为引用将导致未定义的行为,并且我们可以创建一个非const引用来仅形成一个左值变量.不需要从左值变量创建const引用,因为如果它是从非左值变量创建的,它会在该范围内创建一个临时变量(下面的代码).
const int& refa {2};

// basically equals
const int temp_a{2};
const int& refa{temp_a};

我的问题是,如果我们将一个非左值作为参数传递给一个带有const引用的函数,那么临时变量是在调用者的本地范围内还是在函数的本地范围内创建的?我很好奇,如果将参数作为引用返回并使用它将导致未定义的行为.
示例(假设该方法不是内联的):

_declspec(noinline) const int& inMax(const int& a,const int& b)
{
     return a > b ? a : b;
}

int main()
{
    int a{ 5 },b{ 6 };

    // Will the temporary variables for POST decrementation/incrementation result 
    // will be created here or inside inMax(...)
    const int& ret = inMax(a++,b--);
    // is the ret safe to use?
}

解决方法

它将在调用函数的范围内创建(被调用函数无法判断它是否已经传递了它需要破坏的rvalue,还是真正的左值).这是个好消息.坏消息是临时将在包含函数调用的完整表达式结束时被销毁.

编译器会将您的代码转换为:

const int& ret; // Not yet initialized
{
    const int tempA = a++;
    const int tempB = b--;
    ret := inMax(tempA,tempB); // Initialize ret with reference to tempA or tempB
    // destroy tempB,and tempA
}
// ret is Now a dangling reference.

然而.与“返回本地变量的引用”情况不同,在包含函数调用的语句中使用函数结果是有效的.从而:

int ret = inMax(a++,b--);

已验证.在这种情况下,ret是从引用构建的副本 – 尚未悬空.此外,如果函数返回对类对象的引用,则可以安全地在同一语句中调用该类的成员.

说了这么多,这是一个风险很大的领域.如果有人稍后出现并将一个长复杂的语句分成几个部分,它们可能会引入未定义的行为.

原文地址:https://www.jb51.cc/c/115608.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐