我不记得是哪一次谈话,但最近我看了一些来自CppCon 2017的演讲,并且有人提到了某种旁注,那是唯一真正的重载方式{{ 1}}将采用以下方式:
operator=
他明确强调尾随class test {
public:
test& operator=(const test&) &;
};
,但没有说明它的作用。
那它做了什么?
答案 0 :(得分:8)
Ref-qualifiers不是C ++ 17的特性(查看问题的标签),但它是C ++ 11中引入的一个特性。
struct Foo
{
void bar() const & { std::cout << "const lvalue Foo\n"; }
void bar() & { std::cout << "lvalue Foo\n"; }
void bar() const && { std::cout << "const rvalue Foo\n"; }
void bar() && { std::cout << "rvalue Foo\n"; }
};
const Foo&& getFoo() { return std::move(Foo()); }
int main()
{
const Foo c_foo;
Foo foo;
c_foo.bar(); // const lvalue Foo
foo.bar(); // lvalue Foo
getFoo().bar(); // const rvalue Foo
Foo().bar(); // rvalue Foo
}
参见例如以下博客文章简要介绍:
可能从CppCon谈话中解释你的回忆引用的意图,
“......唯一真正的重载方式
operator=
......”
我们访问[over.match.funcs]/1, /4 & /5 [强调我的]:
/ 1 [over.match.funcs]的子条款描述了候选函数集和提交给重载的参数列表 在使用重载决策的每个上下文中的分辨率。 ...
/ 4 对于非静态成员函数,隐式对象参数的类型为
(4.1) - 对于声明没有引用限定符或
&的左值引用” >X
引用限定符- 声明的函数的“对cv
(4.2) - 使用
X
ref-qualifier&&
的rvalue引用”其中
X
是函数所属的类,而cv是 成员函数声明的cv-qualification。 .../ 5 ...对于非静态成员函数声明没有引用限定符,应用其他规则:
- (5.1) - 即使隐式对象参数不是const限定的,也可以将rvalue绑定到参数 在所有其他方面,参数可以转换为类型 隐式对象参数。 [注意:这样的参数是这样的事实 rvalue不会影响隐式转换的排名 序列。 - 尾注]
从上面的/ 5开始,以下重载(省略了显式&
引用限定符)
struct test
{
test& operator=(const test&) { return *this }
}
允许将值分配给r值,例如
int main()
{
test t1;
t1 = test(); // assign to l-value
test() = t1; // assign to r-value
}
但是,如果我们使用&
ref-qualifier明确声明重载,[over.match.funcs]/5.1不适用,并且只要我们不提供使用&&
ref-声明的重载限定符,r值赋值将不被允许。
struct test
{
test& operator=(const test&) & { return *this; }
};
int main()
{
test t1;
t1 = test(); // assign to l-value
test() = t1; // error: passing 'test' as 'this' argument discards qualifiers
}
在声明自定义赋值运算符重载是“唯一真正的重载方式&
”operator=引用限定符提出任何意见>,但是我敢于推测,那么我猜这个声明背后的意图是将排除在 -r-value赋值之外,如上所述。
答案 1 :(得分:2)
根据http://en.cppreference.com/w/cpp/language/member_functions
您的成员函数声明后面的lvalue ref-qualifier
是this
。
换句话说,它要求&&
为l值(隐式对象参数具有对cv-qualified X 的类型lvalue引用)。
还有this
,需要#include <iostream>
struct S {
void f() & { std::cout << "lvalue\n"; }
void f() &&{ std::cout << "rvalue\n"; }
};
int main(){
S s;
s.f(); // prints "lvalue"
std::move(s).f(); // prints "rvalue"
S().f(); // prints "rvalue"
}
作为r值。
从文档中复制( const-,volatile-和ref-qualified成员函数):
children