Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/68.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++ 返回*作为参考是否安全?_C++_Reference_This_This Pointer - Fatal编程技术网

C++ 返回*作为参考是否安全?

C++ 返回*作为参考是否安全?,c++,reference,this,this-pointer,C++,Reference,This,This Pointer,在中经常使用返回对此对象的引用。它还用作一个基础,允许通过调用setter方法链来初始化对象:Params().SetX(1).SetY(1),每个方法都返回对*this的引用 但是返回对*this的引用是否正确。如果我们为临时对象调用返回对此的引用的方法会怎么样: #include <iostream> class Obj { public: Obj(int n): member(n) {} Obj& Me() { return *this; }

在中经常使用返回对此对象的引用。它还用作一个基础,允许通过调用setter方法链来初始化对象:
Params().SetX(1).SetY(1)
,每个方法都返回对*this的引用

但是返回对
*this
的引用是否正确。如果我们为临时对象调用返回对此的引用的方法会怎么样:

#include <iostream>

class Obj
{
public:
    Obj(int n): member(n) {}
    Obj& Me() { return *this; }

    int member;
};

Obj MakeObj(int n)
{
    return Obj(n);
}

int main()
{
    // Are the following constructions are correct:
    std::cout << MakeObj(1).Me().member << std::endl;
    std::cout << Obj(2).Me().member << std::endl;
    Obj(3).Me() = Obj(4);

    return 0;
}
#包括
Obj类
{
公众:
Obj(int n):成员(n){}
Obj&Me(){return*this;}
国际会员;
};
Obj MakeObj(int n)
{
返回Obj(n);
}
int main()
{
//以下结构是否正确:

std::cout是的,这是安全的。临时对象的寿命将持续到语句结束(更准确地说是对创建它的完整表达式的求值)。这由标准保证:

12.2/3:临时对象被销毁,作为计算(词汇上)包含 创建它们的位置

如果绑定到引用,在某些情况下,临时生存期甚至可能会延长。但不要期望出现奇迹。尝试将引用保持在语句之外(例如通过获取地址或分配引用)可能会很快导致UB()

如果在
const
对象上使用这种构造,在尝试返回非
const
ref时也会遇到一些问题(但这与赋值和setter的示例无关)

//以下构造是否正确:

std::cout是的,返回*这是安全的。简单的情况是,这不是临时的,尽管即使是临时的,也应该可以:

临时对象作为计算完整表达式(1.9)的最后一步被销毁,完整表达式(1.9)包含创建临时对象的点。即使该计算以引发异常(C++03§12.2/3)结束,也是如此

换句话说,在你到达分号之前,一切都应该是好的(理论上)

因此,以下代码应该可以工作:

std::cout << MakeObj(1).Me().member << std::endl;

这两种用法都是安全的。只有当调用代码试图保持引用的时间长于当前语句时,才会出现问题,例如,
auto&ref=MakeObj(5.Me();
。是的,您可以创建一个以这种方式指定临时对象的左值(这是我经常纠正使用这些术语的人的原因之一)“临时对象”和“右值”可以互换)我注意到标准库也使用returning*this-:“Return value:*this”。如果标准库使用了不正确的构造,这将很奇怪。:)添加
const Obj&Me()const{Return*this;}
因为重载增加了对常量对象的支持。@StellarCortex是的,举例来说!我只是想提醒大家,在一般情况下,应该仔细考虑操作的常量或非常量,尤其是在返回
*此
作为参考时。当然,对于赋值运算符和设置器,这不应该是一个问题;-)@M:谢谢,我添加了这个例子。谢谢你指出这种过载。它是怎么命名的?C++版本的哪个版本介绍了这个?我认为它是C++ 11,尽管至少MSVC2013不支持。从我可以读到的,我将它称为函数重载在这个PTR的REF限定符上,不知道官方的名字。
// not allowed:
Obj& ref = MakeObj(1);
std::cout << ref.Me().member << std::endl;
// undefined behaviour:
Obj &ref = MakeObj(1).Me();
std::cout << ref.member << std::endl;
std::cout << MakeObj(1).Me().member << std::endl;
const Obj &MakeMeObj(int n) { return Obj(n).Me(); }
std::cout << MakeMeObj(1).member << std::endl;
Obj &Me() & { return *this; }
Obj &Me() && = delete;