Skip to content

Commit 7c63b51

Browse files
committed
右值引用
1 parent f58cc0b commit 7c63b51

File tree

2 files changed

+110
-1
lines changed

2 files changed

+110
-1
lines changed

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,19 @@
336336

337337
22. Variadic Template 进阶 [视频地址](https://www.bilibili.com/video/BV1p4411v7Dh?t=1596&p=11) (以后看看)
338338

339-
339+
23. [右值引用](https://github.com/yangsoon/cpptest/blob/master/c%2B%2B11%3A14/rvalue-reference.cpp) [知乎](https://www.zhihu.com/question/22111546/answer/30801982)
340+
341+
> 右值引用是新型的引用类型 帮助避免不必要的复制
342+
343+
当赋值的右手边是一个右值的时候 左手边的接受端可以偷右手边的资源而不需要执行allocation动作
344+
345+
Lvalue 可以出现在 = 左边 (左值表示变量的地址)
346+
347+
Rvalue 只能出现在 = 右边 (右值表示存储的真实的值)
348+
349+
类的临时对象是一个右值,临时变量一定被当成右值,因为临时对象创建之后 不会再被使用 所以直接把右值数据引用给别的变量,有时候一个左值在后面不会被用到,那么就可以使用move语义 把左值转成右值。
350+
351+
**右值引用我的理解是编译器提供了一个接口 允许你进行赋值的时候直接使用右值的内存空间(其实就是将指针指向这块空间,当然在进行copy ctor和copy asgn的时候你需要自己实现操作,因为当你实现了右值引用的机制后编译器会自动调用你实现的函数),对于一些左值 但是如果在接下来的scope中你用不到了 在进行赋值的时候可以使用move语句将左值转变为右值,因为左值后面用不到了所以你可以把左值指向的内存的指针给删除(注意一定要删除指针,因为当这个左值的scope结束后,编译器会调用析构函数,如果没有删除指针,会把你move出去的这块内存给删除所以就造成了错误)**
340352

341353
**STL**
342354

c++11:14/rvalue-reference.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#include <iostream>
2+
#include <string>
3+
using namespace std;
4+
5+
class MyString{
6+
public:
7+
static size_t DCtor; // 记录默认构造的调用次数
8+
static size_t Ctor; // 记录ctor的调用次数
9+
static size_t CCtor; // 记录copy ctor的调用次数
10+
static size_t CAsgn; // 记录copy asgn的调用次数
11+
static size_t MCtor; // 记录move-ctor的调用次数
12+
static size_t MAsgn; // 记录move-asgn的调用次数
13+
static size_t Dtor; // 记录dtor的调用次数
14+
private:
15+
char* _data;
16+
size_t _len;
17+
void _init_data(const char *s) {
18+
_data = new char[_len+1];
19+
memcpy(_data, s, _len);
20+
_data[_len] = '\0';
21+
}
22+
public:
23+
// 默认构造
24+
MyString(): _data(NULL), _len(0) {++DCtor;}
25+
// 构造
26+
MyString(const char* p) : _len(strlen(p)) {
27+
++Ctor;
28+
_init_data(p);
29+
}
30+
// 拷贝构造
31+
MyString(const MyString& str): _len(str._len) {
32+
++CCtor;
33+
_init_data(str._data);
34+
}
35+
// copy assignment 拷贝赋值
36+
MyString& operator=(const MyString& str){
37+
++CAsgn;
38+
if(this==&str) {
39+
return *this;
40+
}
41+
if(_data) delete _data;
42+
_len = str._len;
43+
_init_data(str._data);
44+
return *this;
45+
}
46+
// move 构造 with noexcept
47+
MyString(MyString&& str) noexcept
48+
// 把指针拷贝一下 长度拷贝一下
49+
:_data(str._data), _len(str._len){
50+
++MCtor;
51+
// 删除指针,如果不删除的话 如果右值被析构的时候编译器会调用析构函数把move的数据给回收
52+
// 配合析构函数来看
53+
str._len = 0;
54+
str._data = NULL; // 重要
55+
}
56+
// move assignment
57+
MyString& operator=(MyString&& str) noexcept{
58+
++MAsgn;
59+
// move
60+
if(this!=&str) {
61+
if(_data) delete _data;
62+
_len = str._len;
63+
_data = str._data;
64+
str._len = 0;
65+
str._data = NULL; // 重要
66+
}
67+
return *this;
68+
}
69+
70+
// 析构函数
71+
virtual ~MyString() {
72+
++DCtor;
73+
if(_data) delete _data;
74+
}
75+
76+
bool operator < (const MyString& rhs) const {
77+
return string(this->_data) < string(rhs._data);
78+
}
79+
80+
bool operator==(const MyString& rhs) const {
81+
return string(this->_data) == string(rhs._data);
82+
}
83+
84+
char* get() const {
85+
return _data;
86+
}
87+
};
88+
size_t MyString::DCtor = 0;
89+
size_t MyString::Ctor = 0;
90+
size_t MyString::CCtor = 0;
91+
size_t MyString::CAsgn = 0;
92+
size_t MyString::MCtor = 0;
93+
size_t MyString::Dtor = 0;
94+
95+
int main() {
96+
97+
}

0 commit comments

Comments
 (0)