1 引用限定符
学了这么多年C++,今天拜读了Scott Meyes的《more effective cpp》,第一次看到这种写法…
引用限定可以让成员函数只能被左值对象调用
或者只能被右值对象调用
。
下面举例说明:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
namespace left_value {
class Hello {
void show() & {
std::cout << "just for left-value\n";
}
};
inline void run() {
Hello t;
t.show(); // ok
Hello{}.show(); // compile error: passing 'left_value::Hello' as 'this' argument discards qualifiers [-fpermissive]
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
namespace right_value {
struct Test {
void show() && {
std::cout << " just for right value\n";
}
};
inline void run() {
Test t;
t.show(); //compile error: passing 'right_value::Test' as 'this' argument discards qualifiers [-fpermissive]
Test{}.show(); //ok
}
}
|
换句话说,引用限定所限定的就是*this,它可以让一些函数只被左值this调用或者右值this调用。
2 同名的左值+右值函数
可以定义多个同名函数,编译器会根据对象的属性,自动判断应该调用哪个函数;
和函数尾部的 const 用法类似。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
namespace both_LR_value {
struct Hello {
// 编译出错: 使用访问控制后, 裸的同名函数不能存在!
// 原因:(裸的同名函数 = 左值函数+右值函数)
/* void f() {
std::cout << "hh\n";
}*/
void f() & {
std::cout << "lvalue object\n";
}
void f() && {
std::cout << "rvalue object\n";
}
};
inline void run() {
Hello t;
t.f(); // lvalue
Hello().f(); // rvalue
}
}
|
3 引用限定符和const 结合
由于 C++ 编译器会对函数名进行mangle
, 我们可以写出以下 4 个重载函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
namespace use_with_const_overload {
struct Hello {
void f() & {
std::cout << "lvalue object\n";
}
void f() && {
std::cout << "rvalue object\n";
}
void f() const & {
std::cout << "const lvalue object\n";
}
void f() const && {
std::cout << "const rvalue object\n";
}
};
inline void run() {
Hello t;
t.f(); // lvalue
Hello().f(); // rvalue
const Hello t3;
t3.f(); // const lvalue
std::move(t3).f(); // const rvalue
}
}
|
总结
没有引用限定符之前,类的左值对象和右值对象,都可以访问其成员函数。
引用限定本质上属于:C++访问控制
相关的语言特性。