类中的引用与常量的初始化问题(含测试代码)

发布时间 2023-04-20 16:17:26作者: ztlsw
 1 #include<iostream>
 2 #include<string>
 3 #include<set>
 4 #include<time.h>
 5 #include<cstring>
 6 #include <vector>
 7 #define LL long long
 8 #define MAXN 100010
 9 using namespace std;
10 int ask_int = 12;
11 double ask_double = 1.2;
12 
13 /*
14 前置注意点:
15     我们定义类中的引用变量,一般是为了捕获类中的成员变量,而不是为了捕获外部变量,因为容易出现未可知的bug
16     这涉及到引用的底层机制,这里仅做引用的举例用(其实是知道的太晚了,代码写的差不多了),不要这样写代码。
17     https://zhuanlan.zhihu.com/p/262210907写的很好,给我很大启发
18     其实我们甚至很少把成员变量定义为引用
19 */
20 class A {
21 public:
22     int &lim_num;
23     const int &lim_const_int;
24     const int const_int;
25     int num;
26     int &&right_num;
27 public:
28     //A() : lim_num(12),right_num(ask_int),const_int(18),lim_const_int(ask_int) {num = 1;cout<<lim_num<<"created"<<endl;}
29     /*
30       编译错误!注意第一项,没加const的引用不能够指向一个右值,而第二项必须用右值赋值
31       报错信息:cannot bind rvalue reference of type 'int&&' to lvalue of type 'int'
32     */
33     //A() : lim_num(ask_double),right_num(ask_double),const_int(18),lim_const_int(20) {}
34     /*编译错误!注意第一项,
35         假设我们赋予的左值和我们的引用类型不同,那么会进行一次强制类型转换,
36         这次强制转换会产生一个临时常量 const int limi = (int) ask_double;(也许,总之系统将其视为一个右值,临时变量具有常性)
37         报错信息:cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'
38     */
39     A() : lim_num(ask_int),right_num(15),const_int(18),lim_const_int(20) {num = 1;cout<<"created"<<endl;}
40 
41     A(int a,int b,int c,int d,int e) : lim_num(a),const_int(b),lim_const_int(c),right_num(165){num = d;cout<<"common created"<<endl;}   
42     //A(const A &a) : lim_num(a.const_int),const_int(a.const_int),lim_const_int(a.lim_const_int),right_num(move(a.right_num)){num = a.num;cout<<"copy created"<<endl;}
43     /*出现bug,最好不要把引用往外指,这个地方可能是因为构造函数把变量副本压入栈中,然后引用绑定了这个栈的临时位置,栈中弹出的时候,就指向了未定义的位置*/
44     A(const A &a) : lim_num(num),const_int(a.const_int),lim_const_int(a.lim_const_int),right_num(move(a.right_num)){num = a.num;cout<<"copy created"<<endl;}
45     /*注意最后一项,我们使用move把左值转换成右值*/
46     A(A &&a) : lim_num(num),const_int(a.const_int),lim_const_int(a.lim_const_int),right_num(move(a.right_num)){num = a.num;cout<<"move created"<<endl;}
47     /*一定要采用括号赋值的方法,不能在大括号里对常量以及引用进行赋值*/
48     ~A(){cout<<" deleted"<<endl;}
49 
50     void printing() {cout<<" "<<lim_num<<" "<<const_int<<" "<<lim_const_int<<" "<<right_num<<" "<<num<<endl;}
51 };
52 
53 A rtti(const A &a)
54 {
55     return a;
56 }
57 
58 int main()
59 {
60     int cxk = 12;
61     //无参测试
62     //A none_val();     //这种写法有误但是编译器不报错给你,它直接跳过,没有输出
63     A *none_val = new A();     //这样写就可以,调用无参构造函数
64     //none_val->func();
65     
66     //一般测试
67     A *common_val = new A(ask_int,14,161,18,244);
68     //A copy_val(*common_val);
69     common_val->printing();
70     //拷贝测试
71     A copy_val = *common_val;
72     //引用外指出现位置bug,第一个引用参数对象变得混乱
73     //copy_val.printing();
74 
75     //移动测试
76     A move_val(12,15,16,187,258);
77     
78     A las = rtti(move_val);
79     //las.printing();
80     return 0;
81 }
82 
83 /*
84 凡是有引用类型的成员变量或者常量类型的变量的类,不能有缺省构造函数。
85 默认构造函数没有对引用成员提供默认的初始化机制,也因此造成引用未初始化的编译错误。
86 并且必须使用初始化列表或直接赋值进行初始化const对象、引用对象。
87 */