C++11右值引用的问题

C++语言 码拜 10年前 (2015-05-11) 1171次浏览 0个评论
 

代码如下:

class Foo
{
public:
	Foo sorted() const &;//---------------成员函数1
	Foo sorted() const &&;//-------------成员函数2
};

Foo Foo::sorted() const &
{
	cout << "sorted() const & " << endl;
	return Foo(*this).sorted();//----------------------(1)
}

Foo Foo::sorted() const &&
{
	cout << "sorted() const && " << endl;
	return *this;
}

int main()
{
	Foo f;
	f.sorted();
	return 0;
}

疑问是,为什么在(1)处调用的是“成员函数2”? 即“Foo(*this)”返回的是右值引用?各位指点一下。。

35分
Foo(*this)是一个临时对象
5分
const &&和const &的区别如下:

一. 右值引用,move语义,完美转发

1. 左值(lvalue)和右值(rvalue)的概念
c++11引入一种新式引用,名曰右值引用,语法:Type&& , const Type&&,区别于之前的&标示的左值引用。为理解右值引用,先要理解左值和右值的概念。
左值,在表达式中,表达式结束时候不会消失,如:obj , *ptr , ptr[index] , ++x
右值,在表达式中,是临时的,表达式结束就会“蒸发”,如:1729 , x + y , std::string(“meow”) , x++ 
区分左值和右值,还有另一种方法:能否取得其地址。
如果能取得其地址,是左值,如:&obj , &*ptr , &ptr[index] , &++x是合法的,是左值;
如果不能取得其地址,是右值,如:&1729 , &(x + y) , &std::string(“meow”) , &x++ 都是不合法的,是右值。
不管是左值还是右值,它要么是modifiable的,要么是const的,如下:
string one(“cute”);
const string two(“fluffy”);
string three() { return “kittens”; }
const string four() { return “are an essential part of a healthy diet”; }

one;     // modifiable lvalue
two;     // const lvalue
three(); // modifiable rvalue
four();  // const rvalue

2. 左值引用和右值引用的绑定特性
左值引用和右值引用各包含modifiable value和const value,故可以分为4种引用形式:

    modifiable lvalue reference
    const lvalue reference
    modifiable rvalue reference
    const rvalue reference

f.sorted();会先调用函数1然后在调用函数2
引用 2 楼 OExpress 的回复:

const &&和const &的区别如下:

一. 右值引用,move语义,完美转发

1. 左值(lvalue)和右值(rvalue)的概念
c++11引入一种新式引用,名曰右值引用,语法:Type&& , const Type&&,区别于之前的&标示的左值引用。为理解右值引用,先要理解左值和右值的概念。
左值,在表达式中,表达式结束时候不会消失,如:obj , *ptr , ptr[index] , ++x
右值,在表达式中,是临时的,表达式结束就会“蒸发”,如:1729 , x + y , std::string(“meow”) , x++ 
区分左值和右值,还有另一种方法:能否取得其地址。
如果能取得其地址,是左值,如:&obj , &*ptr , &ptr[index] , &++x是合法的,是左值;
如果不能取得其地址,是右值,如:&1729 , &(x + y) , &std::string(“meow”) , &x++ 都是不合法的,是右值。
不管是左值还是右值,它要么是modifiable的,要么是const的,如下:
string one(“cute”);
const string two(“fluffy”);
string three() { return “kittens”; }
const string four() { return “are an essential part of a healthy diet”; }

one;     // modifiable lvalue
two;     // const lvalue
three(); // modifiable rvalue
four();  // const rvalue

2. 左值引用和右值引用的绑定特性
左值引用和右值引用各包含modifiable value和const value,故可以分为4种引用形式:

    modifiable lvalue reference
    const lvalue reference
    modifiable rvalue reference
    const rvalue reference

解释的不错,
哪里转发的?

同名同参的成员函数,没问题吗
你的代码同名同参肯定是不好的,可能你的编译器编译没有问题,但是这是错误的(不知道你是不是有什么特殊技巧我没看明白)。至于你的问题,为什么会调用2,原因:(1)处返回的是一个临时值,那默认的会调用右值引用(如果存在的话)。
引用 6 楼 jiangheng0535 的回复:

你的代码同名同参肯定是不好的,可能你的编译器编译没有问题,但是这是错误的(不知道你是不是有什么特殊技巧我没看明白)。至于你的问题,为什么会调用2,原因:(1)处返回的是一个临时值,那默认的会调用右值引用(如果存在的话)。

其实你的理解不对,你说他这是同名同参是错误的,
但事实是,它是同名不同参并且是正确的,构成了重载。关于这一结论,不只是他的编译器可以,你自己可以去试你的编译器也是可以的,当然前提是要支持C++11的这个特性的编译器。
至于这是为什么呢?
原因是成员函数其实有一个隐含的this参数!成员函数后面的const这些就是限定这个this参数的,所以楼主上面的那个代码其实差不多就是如下的形式:
class Foo
{
public:
    Foo sorted(const int * const &this) ;
    Foo sorted(const int * const &&this) ;
};

其实这种用法最主要的用途是为了给类的普通实例和常量实例以不同的行为,比如stl里的vector的【】运算符重载,
当是普通的vector时, 比如:   v[3] = 9; 这个[]应该是返回可修改的引用。
而当这个vector时,还是可以用 v[3] 来读,但不可像上面 v[3] = 9; 这样来改,因为这里的[]返回的是不可修改的常量引用。
这就是利用this参数的重载来达到同名成员函数的不同实现。

更正下上面的示例代码:
class Foo
{
public:
    Foo sorted(const Foo * const &this) ;
    Foo sorted(const Foo * const &&this) ;
};

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明C++11右值引用的问题
喜欢 (0)
[1034331897@qq.com]
分享 (0)

文章评论已关闭!