C++ Primer 5th notes (chap 13 copy control) reference qualifier

1. Problem

Regarding rvalue and lvalue reference member functions, member functions are usually called on an object, regardless of whether the object is an lvalue or an rvalue:

string s1 = "a value",s2 = "another";
auto n = (s1 + s2).find('a');
 
s1 + s2 = "wow";

2. Definition

The above expression assigns an rvalue. In order to prevent this expression, in the new standard, the operand pointed to by the left operand (this) can be forced to be an lvalue by placing a reference after the parameter list Qualifier:

class Foo {
    
    
public:
	Foo& operator=(const Foo&)& {
    
    
		return *this;
	}
	Foo& retFoo() {
    
    
		;	//返回一个引用,retFoo调用是一个左值 
		return *this;
	}

	Foo retVal() {
    
    
		;	//返回一个值,retVal调用是一个右值 
		return Foo();
	}
};

Then

Foo i, j;	//i,j是左值
i = j;
retFoo() = j;	//正确,retFoo()返回一个左值
retVal() = j;	//错误,retVal()返回一个右值
i = retVal();	//正确
j= retFoo();	//正确

2.1 You can use && to force to specify "the left operand is an rvalue"

inline void StrVec::push_back(std::string &&s) 
{
    
    
    chk_n_alloc(); // reallocates the StrVec if necessary
	alloc.construct(first_free++, std::move(s));
}

2.2 Similar to const qualifier, reference qualifier can only be used for non-static member functions

2.3 Must appear in the declaration and definition of the function at the same time.

3. const and reference qualifiers

A function can use both const and reference qualifiers. In this case, the reference qualifier must follow the const qualifier:

class Foo{
    
    
public:
	Foo someMes() & const; 	//错误,const限定符必须在前
	Foo someMes() const &; 	//正确,const限定符必须在前
};

Any function that does not modify data members should be declared as const type.

4. Overload

4.1 Definition

The reference qualifier can be used to distinguish overloaded versions, "&& indicates that the return is an rvalue". And you can combine the reference qualifier and const to distinguish the overloaded version of a member function:

class Foo{
    
    
public:
	Foo sorted() &&;	//可用于改变的右值
	Foo sorted() const &;	//可用于任何类型的Foo
private:
	vector<int> data;
};

//本对象是右值,因此可以原址排序
Foo Foo::sorted() &&
{
    
    
	sort(data.begin(),data.end());
	return *this;
}

//本对象是const或是一个左值,哪种情况我们都不能对其进行原址排序
Foo Foo::sorted() const &
{
    
    
	Foo ret*(*this);			//拷贝一个副本
	sort(ret.begin(),ret.end());	//排序副本
	return ret;	//返回副本
} 
retVal.sorted();	//retVal()是一个右值,调用Foo::sorted() &&
retFoo.sorted();	//retFoo()是一个左值,调用Foo::sorted() const &

4.2 Restrictions on use

  • When we define const member functions, we can define two versions, the only difference is that one version is const-qualified, and the other does not.
  • Reference-qualified functions are not the same. If we define two or more member functions with the same name and the same parameter list, we must add reference qualifiers to all functions, or none of them:
class Foo
{
    
    
	Foo sorted() &&;
	Foo sorted() const;	//错误,必须加上引用限定符
	using Comp = bool (const int&,const int&);
	Foo sorted(Comp*);	//正确,不同的参数列表
	Foo sorted(Comp*);	//正确,两个版本都没有使用引用限定符
};

Guess you like

Origin blog.csdn.net/thefist11cc/article/details/113914161