首页
社区
课程
招聘
[原创] [calleng的逆向日记] 23/03/30 (C++概念构建篇01) 补充完毕
发表于: 2023-3-30 23:47 12930

[原创] [calleng的逆向日记] 23/03/30 (C++概念构建篇01) 补充完毕

2023-3-30 23:47
12930

入门学习逆向的个人笔记,预览(欢迎探讨)

  • C/C++的学习和数据结构

[原创] [calleng的逆向日记] 22y11m-23y3m29d 实现macOS编辑, iOS端编译和调试C/C++
[原创] [calleng的逆向日记] 23/03/30 (C++概念构建篇01) 补充完毕
[分享] [calleng的逆向日记] 22y11m-23y6m7d Win10Arm下的 gdb调试.[数据结构/严蔚敏-之迷宫问题]

  • iOS的学习和逆向

[分享] IOS软件安全工程师技能表(2017.7by非虫) (为自己学习导航) 图片不清楚下面有导图下载
[分享] Frida-Tool的一些 介绍, 和在 iOS下的一些用法 [个人笔记汇总]
[原创] [calleng的逆向日记] 弹窗的修改原理-OC篇 [源码学习和HOOK实践]23/09/24 --待续
[讨论] [calleng的逆向日记] 自学iOS逆向时候,如何自己解决问题.
[分享] [calleng逆向日记] iOS crackMe的破解 与 Frida(Objection) 的入门使用(thanks to roysue)
[分享] (iOS Hook原理,OC底层实现)Frida前置知识的(royuse)的一些知识注解(图片三次压缩失真,详情见附件)
[原创] (calleng逆向日记)Frida前置知识, ObjC runtime的"反射"-KVC-实例代码理解和分析
[分享] [calleng的逆向日记] Frida 前置知识, 类与方法的底层实现, 逻辑批注, (参考AloneMonkey的书)
[原创] (calleng逆向日记)Frida前置知识, ObjC runtime的"反射" KVC实例Demo分析第二部(Demo底部下载)
[分享] [calleng的逆向日记] iOS crackMe and Frida(Objection) Get Started (Oct,16th)
[分享] [calleng的逆向日记] Frida在iOS上内存漫游与黑盒调用 Get Started Section 4


占坑,12点后再补充

目前购买了董洪伟老师的C++17从入门到精通, book 包含了12个章节,
✅ 1, C++基础
✅ 2, 变量和类型
✅ 3,运算符号和表达式
✅ 4,语句
✅ 5,复合类型:数组,指针和引用
✅ 6,函数
✅ 7,类和对象
✅ 8,运算符重载
✅ 9,派生类
✅ 10,模版
✅ 11,移动语义
❌ 12,函数指针,函数对象, Lambda表达式
❌ 13,C++标准库介绍
❌ 14,异常处理

✅ 代表学习完成,
❌ 代表即将学习.

之前学习 Objective-C的时候, 花了1000 rmb 的课程, 1080p的课程给我搞成了, 480p糊的画面, 腾讯课堂话说无果. 看来只能投诉在工信部投诉他们.

于是对腾讯课堂买课不敢恭维,所以就 只要没有1080p的课都是 LJ, 所以,找到了
董老师的 6小时掌握 c 语言1080p,学习后真是享受,后来发现了他出了C++的课程,PPT都写好发布出来,所以买了book.
后来 买了 编程网的 永久会员. 所以, 当作C++的补充资料.

类和对象

2.13 static静态成员函数详解

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
using namespace std;
 
class Student{
public:
    Student(char *name, int age, float score);
    void show();
public:  //声明静态成员函数
    static int getTotal();
    static float getPoints();
private:
    static int m_total;  //总人数
    static float m_points;  //总成绩
private:
    char *m_name;
    int m_age;
    float m_score;
};
 
int Student::m_total = 0;
float Student::m_points = 0.0;
 
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){
    m_total++;
    m_points += score;
}
void Student::show(){
    cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<endl;
}
//定义静态成员函数
int Student::getTotal(){
    return m_total;
}
float Student::getPoints(){
    return m_points;
}
 
int main(){
    (new Student("小明", 15, 90.6)) -> show();
    (new Student("李磊", 16, 80.5)) -> show();
    (new Student("张华", 16, 99.0)) -> show();
    (new Student("王康", 14, 60.8)) -> show();
 
    int total = Student::getTotal();
    float points = Student::getPoints();
    cout<<"当前共有"<<total<<"名学生,总成绩是"<<points<<",平均分是"<<points/total<<endl;
 
    return 0;
}

2.14 const成员变量,成员函数(常成员函数)

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
class Student{
public:
    Student(char *name, int age, float score);
    void show();
    //声明常成员函数
    char *getname() const;
    int getage() const;
    float getscore() const;
private:
    char *m_name;
    int m_age;
    float m_score;
};
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
void Student::show(){
    cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<endl;
}
//定义常成员函数
char * Student::getname() const{
    return m_name;
}
int Student::getage() const{
    return m_age;
}
float Student::getscore() const{
    return m_score;
}

###2.15 const对象(常对象)

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
28
29
30
31
32
33
34
35
36
37
#include <iostream>
using namespace std;
class Student{
public:
    Student(char *name, int age, float score);
public:
    void show();
    char *getname() const;
    int getage() const;
    float getscore() const;
private:
    char *m_name;
    int m_age;
    float m_score;
};
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
void Student::show(){
    cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<endl;
}
char * Student::getname() const{
    return m_name;
}
int Student::getage() const{
    return m_age;
}
float Student::getscore() const{
    return m_score;
}
int main(){
    const Student stu("小明", 15, 90.6);
    //stu.show();  //error
    cout<<stu.getname()<<"的年龄是"<<stu.getage()<<",成绩是"<<stu.getscore()<<endl;
    const Student *pstu = new Student("李磊", 16, 80.5);
    //pstu -> show();  //error
    cout<<pstu->getname()<<"的年龄是"<<pstu->getage()<<",成绩是"<<pstu->getscore()<<endl;
    return 0;
}

2.16 友元函数和友元类(friend关键字)

1) 将非成员函数声明为友元函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
using namespace std;
class Student{
public:
    Student(char *name, int age, float score);
public:
    friend void show(Student *pstu);  //将show()声明为友元函数
private:
    char *m_name;
    int m_age;
    float m_score;
};
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
//非成员函数
void show(Student *pstu){
    cout<<pstu->m_name<<"的年龄是 "<<pstu->m_age<<",成绩是 "<<pstu->m_score<<endl;
}
int main(){
    Student stu("小明", 15, 90.6);
    show(&stu);  //调用友元函数
    Student *pstu = new Student("李磊", 16, 80.5);
    show(pstu);  //调用友元函数
    return 0;
}

2) 将其他类的成员函数声明为友元函数

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
using namespace std;
class Address;  //提前声明Address类
//声明Student类
class Student{
public:
    Student(char *name, int age, float score);
public:
    void show(Address *addr);
private:
    char *m_name;
    int m_age;
    float m_score;
};
//声明Address类
class Address{
private:
    char *m_province;  //省份
    char *m_city;  //城市
    char *m_district;  //区(市区)
public:
    Address(char *province, char *city, char *district);
    //将Student类中的成员函数show()声明为友元函数
    friend void Student::show(Address *addr);
};
//实现Student类
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
void Student::show(Address *addr){
    cout<<m_name<<"的年龄是 "<<m_age<<",成绩是 "<<m_score<<endl;
    cout<<"家庭住址:"<<addr->m_province<<"省"<<addr->m_city<<"市"<<addr->m_district<<"区"<<endl;
}
//实现Address类
Address::Address(char *province, char *city, char *district){
    m_province = province;
    m_city = city;
    m_district = district;
}
int main(){
    Student stu("小明", 16, 95.5f);
    Address addr("陕西", "西安", "雁塔");
    stu.show(&addr);
 
    Student *pstu = new Student("李磊", 16, 80.5);
    Address *paddr = new Address("河北", "衡水", "桃城");
    pstu -> show(paddr);
    return 0;
}

3) 友元类

  • 不仅可以将一个函数声明为一个类的“朋友”,还可以将整个类声明为另一个类的“朋友”,这就是友元类。友元类中的所有成员函数都是另外一个类的友元函数。
  • 例如将类 B 声明为类 A 的友元类,那么类 B 中的所有成员函数都是类 A 的友元函数,可以访问类 A 的所有成员,包括 public、protected、private 属性的。
  • 更改上例的代码,将 Student 类声明为 Address 类的友元类:
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
using namespace std;
class Address;  //提前声明Address类
//声明Student类
class Student{
public:
    Student(char *name, int age, float score);
public:
    void show(Address *addr);
private:
    char *m_name;
    int m_age;
    float m_score;
};
//声明Address类
class Address{
public:
    Address(char *province, char *city, char *district);
public:
    //将Student类声明为Address类的友元类
    friend class Student;
private:
    char *m_province;  //省份
    char *m_city;  //城市
    char *m_district;  //区(市区)
};
//实现Student类
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
void Student::show(Address *addr){
    cout<<m_name<<"的年龄是 "<<m_age<<",成绩是 "<<m_score<<endl;
    cout<<"家庭住址:"<<addr->m_province<<"省"<<addr->m_city<<"市"<<addr->m_district<<"区"<<endl;
}
//实现Address类
Address::Address(char *province, char *city, char *district){
    m_province = province;
    m_city = city;
    m_district = district;
}
int main(){
    Student stu("小明", 16, 95.5f);
    Address addr("陕西", "西安", "雁塔");
    stu.show(&addr);
 
    Student *pstu = new Student("李磊", 16, 80.5);
    Address *paddr = new Address("河北", "衡水", "桃城");
    pstu -> show(paddr);
    return 0;
}

2.17类其实也是一种作用域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<iostream>
using namespace std;
class A{
public:
    typedef int INT;
    static void show();
    void work();
};
void A::show(){ cout<<"show()"<<endl; }
void A::work(){ cout<<"work()"<<endl; }
int main(){
    A a;
    a.work();  //通过对象访问普通成员
    a.show();  //通过对象访问静态成员
    A::show();  //通过类访问静态成员
    A::INT n = 10//通过类访问 typedef 定义的类型
    return 0;
}

####定义在类外部的成员

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
#include<iostream>
using namespace std;
class A{
public:
    typedef char* PCHAR;
public:
    void show(PCHAR str);
private:
    int n;
};
void A::show(PCHAR str){
    cout<<str<<endl;
    n = 10;
}
 
//A::PCHAR A::show(PCHAR str){
//    cout<<str<<endl;
//    n = 10;
//    return str;
//}
 
int main(){
    A obj;
    obj.show("http://c.biancheng.net");
    return 0;
}

2.18 class和struct到底有什么区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
using namespace std;
struct Student{
    Student(char *name, int age, float score);
    void show();
    char *m_name;
    int m_age;
    float m_score;
};
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
void Student::show(){
    cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<endl;
}
int main(){
    Student stu("小明", 15, 92.5f);
    stu.show();
    Student *pstu = new Student("李华", 16, 96);
    pstu -> show();
    return 0;
}

2.19 string详解,C++字符串详解-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <string>
using namespace std;
int main(){
    string s1;
    string s2 = "c plus plus";
    string s3 = s2;
    string s4 (5, 's');
    string s = "http://c.biancheng.net";
    int len = s.length();
    cout<<len<<endl;
    cout<<s1.length()<<endl;
    cout<<s2.length()<<endl;
    cout<<s3.length()<<endl;
    cout<<s4.length()<<endl;
}

2.19 string详解,字符串详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <string>
using namespace std;
int main(){
    string s1;
    string s2 = "c plus plus";
    string s3 = s2;
    string s4 (5, 's');
    string s = "http://c.biancheng.net";
    int len = s.length();
    cout<<len<<endl;
    cout<<s1.length()<<endl;
    cout<<s2.length()<<endl;
    cout<<s3.length()<<endl;
    cout<<s4.length()<<endl;
}

string 字符串的输入输出

1
2
3
4
5
6
7
8
9
#include <iostream>
#include <string>
using namespace std;
int main(){
    string s;
    cin>>s;  //输入字符串
    cout<<s<<endl;  //输出字符串
    return 0;
}

访问字符串中的字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <string>
using namespace std;
int main(){
    string s = "i like my father and my mother!",s3;
    for(int i=0,len=s.length(); i<len; i++){
        cout<<s[i]<<" ";
    }
    cout<<endl;
    s3 = "拼";
    s.insert(5,s3);
    cout<<s<<endl;
    return 0;
}

字符串的拼接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <string>
using namespace std;
int main(){
    string s1 = "first ";
    string s2 = "second ";
    char *s3 = "third ";
    char s4[] = "fourth ";
    char ch = '@';
    string s5 = s1 + s2;
    string s6 = s1 + s3;
    string s7 = s1 + s4;
    string s8 = s1 + ch;
 
    cout<<s5<<endl<<s6<<endl<<s7<<endl<<s8<<endl;
    return 0;
}

string 字符串的增删改查,一. 插入字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>
using namespace std;
int main(){
    string s1, s2, s3;
    s1 = s2 = "1234567890";
    s3 = "aaa";
    s1.insert(5, s3);
    cout<< s1 <<endl;
    s2.insert(7, "bbb");
    cout<< s2 <<endl;
    return 0;
}

string 字符串的增删改查,二. 删除字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>
using namespace std;
int main(){
    string s1, s2, s3;
    s1 = s2 = s3 = "1234567890";
    s2.erase(5);
    s3.erase(5, 3);
    cout<< s1 <<endl;
    cout<< s2 <<endl;
    cout<< s3 <<endl;
    return 0;
}

string 字符串的增删改查,三. 提取子字符串

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <string>
using namespace std;
int main(){
    string s1 = "first second third";
    string s2;
    s2 = s1.substr(6, 6);
    cout<< s1 <<endl;
    cout<< s2 <<endl;
    return 0;
}

string 字符串的增删改查,四. 字符串查找

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>
using namespace std;
int main(){
    string s1 = "first second third";
    string s2 = "second";
    int index = s1.find(s2,5);//第一个参数为待查找的子字符串。第二个参数为开始查找的位置(下标);如果不指明,则从第0个字符开始查找。
    if(index < s1.length())
        cout<<"Found at index : "<< index <<endl;
    else
        cout<<"Not found"<<endl;
    return 0;
}

string 字符串的增删改查, 四. 字符串查找 2) rfind() 函数
不同的是 find() 函数从第二个参数开始往后查找,而 rfind() 函数则最多查找到第二个参数处

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>
using namespace std;
int main(){
    string s1 = "first second third";
    string s2 = "second";
    int index = s1.rfind(s2,6); //而 rfind() 函数则最多查找到第二个参数处
    if(index < s1.length())
        cout<<"Found at index : "<< index <<endl;
    else
        cout<<"Not found"<<endl;
    return 0;
}

C++引用

C++引用10分钟入门

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/*
 *C++引用10分钟入门教程
 * 引用可以看做是数据的一个别名,通过这个别名和原来的名字都能够找到这份数据
 * 引用必须在定义的同时初始化,并且以后也要从一而终,不能再引用其它数据,这有点类似于常量(const 变量)。
 */
#if 0
#include <iostream>
using namespace std;
int main() {
    int a = 99;
    int &r = a;
    cout << a << ", " << r << endl;
    cout << &a << ", " << &r << endl;
    return 0;
}
#endif
 
 
/*
 *注意,引用在定义时需要添加&,在使用时不能添加&,使用时添加&表示取地址
 * 由于引用 r 和原始变量 a 都是指向同一地址,所以通过引用也可以修改原始变量中所存储的数据,请看下面的例子:
 * 如果读者不希望通过引用来修改原始的数据,那么可以在定义时添加 const 限制,形式为:const type &name = value;
 */
#if 0
#include <iostream>
using namespace std;
int main() {
    int a = 99;
    int &r = a;
    r = 47;
    cout << a << ", " << r << endl;
    return 0;
}
#endif
 
 
/*
 *一个能够展现按引用传参的优势的例子就是交换两个数的值,请看下面的代码:
 */
#if 0
#include <iostream>
using namespace std;
void swap1(int a, int b);
void swap2(int *p1, int *p2);
void swap3(int &r1, int &r2);
int main() {
    int num1, num2;
    cout << "Input two integers: ";
    cin >> num1 >> num2;
    swap1(num1, num2);
    cout << num1 << " " << num2 << endl;
    cout << "Input two integers: ";
    cin >> num1 >> num2;
    swap2(&num1, &num2);
    cout << num1 << " " << num2 << endl;
    cout << "Input two integers: ";
    cin >> num1 >> num2;
    swap3(num1, num2);
    cout << num1 << " " << num2 << endl;
    return 0;
}
//直接传递参数内容
void swap1(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
}
//传递指针
void swap2(int *p1, int *p2) {
    int temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}
//按引用传参
void swap3(int &r1, int &r2) {
    int temp = r1;
    r1 = r2;
    r2 = temp;
}
#endif

引用作为函数返回值

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*C++引用作为函数返回值
 *引用除了可以作为函数形参,还可以作为函数返回值
 * 在将引用作为函数返回值时应该注意一个小问题,就是不能返回局部数据(例如局部变量、局部对象、局部数组等)的引用,
 * 因为当函数调用完成后局部数据就会被销毁,有可能在下次使用时数据就不存在了,C++ 编译器检测到该行为时也会给出警告。
 */
#if 0
#include <iostream>
using namespace std;
int &plus10(int &r) {
    r += 10;
    return r;
}
int main() {
    int num1 = 10;
    int num2 = plus10(num1);
    cout << num1 << " " << num2 << endl;
    return 0;
}
#endif
 
 
/*
 *更改上面的例子,让 plus10() 返回一个局部数据的引用:
 */
#if 0
#include <iostream>
using namespace std;
int &plus10(int &r) {
    int m = r + 10;
    return m;  //返回局部数据的引用
}
int main() {
    int num1 = 10;
    int num2 = plus10(num1);  //20
    cout << num2 << endl;
    int &num3 = plus10(num1); //30
    int &num4 = plus10(num3); //20
    cout << num3 << " " << num4 << endl;
    return 0;
}
#endif
 
 
/*
 *C++引用在本质上是什么,它和指针到底有什么区别?
 */
#if 0
#include <iostream>
using namespace std;
int main(){
    int a = 99;
    int &r = a;
    cout<<a<<", "<<r<<endl;
    cout<<&a<<", "<<&r<<endl;
    return 0;
}
 
#endif
 
 
/*
 *成员变量 r 是 private 属性的,不能直接通过对象来访问,
 * 但是借助强大的指针和类型转换,我们依然可以得到它的内容,
 * 只不过这种方法有点蹩脚,我们将在《突破访问权限的限制(C++ Hack)》一节中详细阐述,读者暂时不必理解,
 * 只要知道第 20 行代码是用来输出 r 本身的内容的即可。
 */
#if 0
#include <iostream>
#include <iomanip>
using namespace std;
int num = 99;
class A{
public:
    A();
private:
    int n;
    int &r;
};
A::A(): n(0), r(num){}
int main (){
    A *a = new A();
    cout<<sizeof(A)<<endl;  //输出A类型的大小
    cout<<hex<<showbase<<*((int*)a + 1)<<endl;  //输出r本身的内容 ||代码中,hex表示以十六进制输出,showbase表示添加十六进制前缀0x
    cout<<&num<<endl;  //输出num变量的地址
    return 0;
}
/* 从运行结果可以看出:
 * 成员变量 r 是占用内存的,如果不占用的话,sizeof(A)的结果应该为 16
 * r 存储的内容是0xb0000000,也即变量 num 的地址0x100434060
 *
 * 其实引用只是对指针进行了简单的封装,它的底层依然是通过指针实现的,
 * 引用占用的内存和指针占用的内存长度一样,
 * 32 位环境下是 4 个字节,在 64 位环境下是 8 个字节,在iOS系统下,字节对齐所以16个字节
 *
 * 之所以不能获取引用的地址,是因为编译器进行了内部转换
 *
 * 使用&r取地址时,编译器会对代码进行隐式的转换,使得代码输出的是 r 的内容(a 的地址),而不是 r 的地址,
 * 这就是为什么获取不到引用变量的地址的原因。也就是说,不是变量 r 不占用内存,而是编译器不让获取它的地址。
 *
 * 引用虽然是基于指针实现的,但它比指针更加易用,从上面的两个例子也可以看出来,通过指针获取数据时需要加*,书写麻烦,而引用不需要,它和普通变量的使用方式一样。
 * C++ 的发明人 Bjarne Stroustrup 也说过,他在 C++ 中引入引用的直接目的是为了让代码的书写更加漂亮,尤其是在运算符重载中,不借助引用有时候会使得运算符的使用很麻烦。
 */
#endif

引用和指针的其他区别

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
/*
 *引用和指针的其他区别
 *
 * 1) 引用必须在定义时初始化,并且以后也要从一而终,不能再指向其他数据
 * 2) 可以有 const 指针,但是没有 const 引用。
 * 3) 指针可以有多级,但是引用只能有一级
 * 4) 指针和引用的自增(++)自减(--)运算意义不一样。对指针使用 ++ 表示指向下一份数据,对引用使用 ++ 表示它所指代的数据本身加 1;自减(--)也是类似的道理。
 */
 
#if 0
#include <iostream>
using namespace std;
int main (){
    int a = 10;
    int &r = a;
    r++;//对引用使用 ++ 表示它所指代的数据本身加 1
    cout<<r<<endl;
 
    int arr[2] = { 27, 84 };
    int *p = arr;
    p++;
    cout<<*p<<endl; //对指针使用 ++ 表示指向下一份数据
    return 0;
}
#endif

引用不能绑定到临时数据

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/*
 *C++引用不能绑定到临时数据
 */
#if 0
#include <iostream>
using namespace std;
typedef struct{
    int a;
    int b;
} S;
//这里用到了一点新知识,叫做运算符重载,我们会在《运算符重载》一章中详细讲解
S operator+(const S &A, const S &B){
    S C;
    C.a = A.a + B.a;
    C.b = A.b + B.b;
    return C;
}
S func(){
    S a;
    a.a = 100;
    a.b = 200;
    return a;
}
int main(){
    S s1 = {23, 45};
    S s2 = {90, 75};
    S *p1 = &(s1 + s2);
    S *p2 = &(func());
    cout<<p1<<", "<<p2<<endl;
    return 0;
}
#endif
 
 
/*
 *引用也不能指代临时数据
 */
#if 0
typedef struct{
    int a;
    int b;
} S;
int func_int(){
    int n = 100;
    return n;
}
S func_s(){
    S a;
    a.a = 100;
    a.b = 200;
    return a;
}
//这里用到了一点新知识,叫做运算符重载,我们会在《运算符重载》一章中详细讲解
S operator+(const S &A, const S &B){
    S C;
    C.a = A.a + B.a;
    C.b = A.b + B.b;
    return C;
}
int main(){
    //下面的代码在GCC和Visual C++下都是错误的
    int m = 100, n = 36;//28~33 行代码在 GCC 和 Visual C++ 下都不能编译通过
    int &r1 = m + n;//28~33 行代码在 GCC 和 Visual C++ 下都不能编译通过
    int &r2 = m + 28;//28~33 行代码在 GCC 和 Visual C++ 下都不能编译通过
    int &r3 = 12 * 3;//28~33 行代码在 GCC 和 Visual C++ 下都不能编译通过
    int &r4 = 50;//28~33 行代码在 GCC 和 Visual C++ 下都不能编译通过
    int &r5 = func_int();//28~33 行代码在 GCC 和 Visual C++ 下都不能编译通过
 
    //下面的代码在GCC下是错误的,在Visual C++下是正确的
    S s1 = {23, 45};//38~39 行代码在 Visual C++ 下能够编译通过,但是在 GCC 下编译失败。
    S s2 = {90, 75};//38~39 行代码在 Visual C++ 下能够编译通过,但是在 GCC 下编译失败。
    S &r6 = func_s();
    S &r7 = s1 + s2;
    return 0;/*
 * 在 GCC 下,引用不能指代任何临时数据,不管它保存到哪里;
 * 在 Visual C++ 下,引用只能指代位于内存中(非代码区)的临时数据,不能指代寄存器中的临时数据。
 *
 * 关于常量表达式
 *诸如 100200+3434.5*233+7/3 等不包含变量的表达式称为常量表达式(Constant expression)。
 *总起来说,常量表达式的值虽然在内存中,但是没有办法寻址,所以也不能使用&来获取它的地址,更不能用指针指向它。
 * isOdd() 函数用来判断一个数是否为奇数,它的参数是引用类型,只能传递变量,不能传递常量或者表达式。
 */
}
#endif

编译器会为const引用创建临时变量

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
28
29
30
31
32
33
34
35
36
37
38
/*
 *--------3.4 -----编译器会为const引用创建临时变量---------
 */
#if 1
typedef struct{
    int a;
    int b;
} S;
int func_int(){
    int n = 100;
    return n;
}
S func_s(){
    S a;
    a.a = 100;
    a.b = 200;
    return a;
}
S operator+(const S &A, const S &B){
    S C;
    C.a = A.a + B.a;
    C.b = A.b + B.b;
    return C;
}
int main(){
    int m = 100, n = 36;
    const int &r1 = m + n;
    const int &r2 = m + 28;
    const int &r3 = 12 * 3;
    const int &r4 = 50;
    const int &r5 = func_int();
    S s1 = {23, 45};
    S s2 = {90, 75};
    const S &r6 = func_s();
    const S &r7 = s1 + s2;
    return 0;
}
#endif

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2023-11-8 00:29 被calleng编辑 ,原因: 修改大纲,填充内容
收藏
免费 2
支持
分享
最新回复 (4)
雪    币: 3573
活跃值: (31026)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
被题目吸引而来
2023-3-31 09:17
0
雪    币: 31
活跃值: (3269)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
跑完了外送, 继续学习, 填坑来了.
2023-3-31 09:31
0
雪    币: 258
活跃值: (1747)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
要不大家帮他写了吧,好让他送外卖
2023-3-31 10:08
0
雪    币: 31
活跃值: (3269)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
送完了,好不,坑填的差不多了,可以看了.
2023-3-31 10:40
0
游客
登录 | 注册 方可回帖
返回
//