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

前端之家收集整理的这篇文章主要介绍了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是从引用构建的副本 – 尚未悬空.此外,如果函数返回对类对象的引用,则可以安全地在同一语句中调用该类的成员.

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

猜你在找的C&C++相关文章