关键词搜索

源码搜索 ×
×

const用法总结以及构造函数、析构函数、拷贝构造函数的深入剖析

发布2013-05-14浏览8045次

详情内容

     1. 用const时候,通常需要初始化:

 

  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. int const i;
  6. // error C2734: 'i' : const object must be initialized if not extern
  7. return 0;
  8. }
  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. int i = 1;
  6. const int j = i; // 只能在初始化时赋值
  7. i = j;
  8. //j = i; 此语句错误
  9. return 0;
  10. }

   2. 如果涉及指针,会稍微复杂一点:

 

 

  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. int i = 1;
  6. const int *p = &i; // 星在const右,表示*p不能直接改变,但p可变
  7. // *p = 2; 错误:不能直接改变
  8. i = 2; // 正确: *p不能变,但i可以变
  9. int j = 3;
  10. int *q = &j;
  11. p = q; // 正确: p可变
  12. return 0;
  13. }
  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. int i = 1;
  6. int const*p = &i; // 星在const右,表示*p不能直接改变,但p可变
  7. // *p = 2; 错误:不能直接改变
  8. i = 2; // 正确: *p不能变,但i可以变
  9. int j = 3;
  10. int *q = &j;
  11. p = q; // 正确: p可变
  12. return 0;
  13. }
  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. int i = 1;
  6. int *const p = &i; // 星在const左,表示p不能改变,但*p可直接变
  7. *p = 2;
  8. i = 2;
  9. int j = 3;
  10. int *q = &j;
  11. //p = q; 错误:p不能变
  12. return 0;
  13. }

     总结:星在const左,p不能改变;星在const右,*p不能直接改变;星在两个const中间,p不能改变,*p也不能直接改变。

 

3.  用const来修饰函数参数:

 

  1. #include<iostream>
  2. using namespace std;
  3. int increase(const int x)
  4. {
  5. // x = x + 1; 错误:x不能改变
  6. return x;
  7. }
  8. int main()
  9. {
  10. return 0;
  11. }
  1. #include<iostream>
  2. using namespace std;
  3. void fun(const int *p)
  4. {
  5. p = NULL; // 正确
  6. // *p = 0; 错误:不能直接改变*p
  7. }
  8. int main()
  9. {
  10. return 0;
  11. }
  1. #include<iostream>
  2. using namespace std;
  3. void fun(const int &x)
  4. {
  5. // x = x + 1; 错误:x不能改变
  6. }
  7. int main()
  8. {
  9. return 0;
  10. }
  1. #include<iostream>
  2. using namespace std;
  3. class A{};
  4. // fun1比fun2的效率要高
  5. void fun1(const A &x) // 不存在对象拷贝
  6. {
  7. }
  8. A fun2(const A x) // 存在对象拷贝
  9. {
  10. return x;
  11. }
  12. int main()
  13. {
  14. A a;
  15. fun1(a);
  16. a = fun2(a);
  17. return 0;
  18. }

4. 用const修饰函数的返回值

  1. #include<iostream>
  2. using namespace std;
  3. const int fun(int x) // 这种情况下,const没有任何作用
  4. {
  5. x = x + 1;
  6. return x;
  7. }
  8. int main()
  9. {
  10. int a = 1;
  11. int b = fun(a);
  12. return 0;
  13. }
  1. #include<iostream>
  2. using namespace std;
  3. const char *fun(char str[]) // 返回指针的类型是 const char * 类型的
  4. {
  5. return str;
  6. }
  7. int main()
  8. {
  9. char s[] = "hello";
  10. // char *p = fun(s); 错误
  11. const char *p = fun(s);
  12. cout << p << endl;
  13. return 0;
  14. }
  1. #include<iostream>
  2. using namespace std;
  3. class A{};
  4. A fun1()
  5. {
  6. A x;
  7. return x;
  8. }
  9. A *fun2(A *q)
  10. {
  11. return q;
  12. }
  13. A &fun3(A &x)
  14. {
  15. return x;
  16. }
  17. int fun4()
  18. {
  19. int i = 1;
  20. return i;
  21. }
  22. int main()
  23. {
  24. A a, b, *p;
  25. fun1() = a; // 语法上正确,但风格不好
  26. // fun2(p) = NULL; // 语法上错误
  27. fun3(b) = a; // 语法上正确,但风格不好
  28. int i;
  29. // fun4() = i; // 语法上错误
  30. return 0;
  31. }

 

    为了防止上述的fun1() = a;和fun3(b) = a;这样的语句,就采用const修饰返回值(其实,我有点纳闷:哪个傻瓜程序员会这么调用函数?),改正后的程序为:

 

  1. #include<iostream>
  2. using namespace std;
  3. class A{};
  4. const A fun1()
  5. {
  6. A x;
  7. return x;
  8. }
  9. const A *fun2(A *q) // 可以不需要const, 但加上后,肯定不错
  10. {
  11. return q;
  12. }
  13. const A &fun3(A &x)
  14. {
  15. return x;
  16. }
  17. const int fun4() // 可以不需要const,但加上后,肯定不错
  18. {
  19. int i = 1;
  20. return i;
  21. }
  22. int main()
  23. {
  24. A a, b, *p;
  25. // fun1() = a; // 语法上错误
  26. // fun2(p) = NULL; // 语法上错误
  27. // fun3(b) = a; // 语法上错误
  28. int i;
  29. // fun4() = i; // 语法上错误
  30. return 0;
  31. }


     现在,一切都明白了吧!在上面的程序中,我们注意到有返回引用的情况,下面来看看引用是如何返回的:

 

  1. #include <iostream>
  2. using namespace std;
  3. int &fun(int &x)
  4. {
  5. return x;
  6. }
  7. int main()
  8. {
  9. int a = 1;
  10. int &b = fun(a); // 注意初始化引用的方法
  11. cout << a << endl; // 1
  12. cout << b << endl; // 1
  13. b = 2;
  14. cout << a << endl; // 2
  15. cout << b << endl; // 2
  16. b = 3;
  17. cout << a << endl; // 3
  18. cout << b << endl; // 3
  19. return 0;
  20. }

     一切都明白了。最后欣赏几个程序,补补C++的基本知识:

 

 

  1. #include <iostream>
  2. using namespace std;
  3. class A
  4. {
  5. public:
  6. // 构造函数
  7. A()
  8. {
  9. cout << "constructor" << endl;
  10. }
  11. // 析构函数
  12. ~A()
  13. {
  14. cout << "destructor" << endl;
  15. }
  16. // 拷贝构造函数
  17. A(A &)
  18. {
  19. cout << "copy constructor" << endl;
  20. }
  21. };
  22. void fun(A a)
  23. {
  24. }
  25. int main()
  26. {
  27. A a;
  28. return 0;
  29. }

    结果为:

 

constructor

destructor

 

  1. #include <iostream>
  2. using namespace std;
  3. class A
  4. {
  5. public:
  6. // 构造函数
  7. A()
  8. {
  9. cout << "constructor" << endl;
  10. }
  11. // 析构函数
  12. ~A()
  13. {
  14. cout << "destructor" << endl;
  15. }
  16. // 拷贝构造函数
  17. A(A &)
  18. {
  19. cout << "copy constructor" << endl;
  20. }
  21. };
  22. void fun(A a)
  23. {
  24. }
  25. int main()
  26. {
  27. A a;
  28. fun(a);
  29. return 0;
  30. }

    结果为:

 

constructor
copy constructor
destructor
destructor

  1. #include <iostream>
  2. using namespace std;
  3. class A
  4. {
  5. public:
  6. // 构造函数
  7. A()
  8. {
  9. cout << "constructor" << endl;
  10. }
  11. // 析构函数
  12. ~A()
  13. {
  14. cout << "destructor" << endl;
  15. }
  16. // 拷贝构造函数
  17. A(A &)
  18. {
  19. cout << "copy constructor" << endl;
  20. }
  21. };
  22. void fun(A &a)
  23. {
  24. }
  25. int main()
  26. {
  27. A a;
  28. fun(a);
  29. return 0;
  30. }

    结果为:

 

constructor
destructor

  1. #include <iostream>
  2. using namespace std;
  3. class A
  4. {
  5. public:
  6. // 构造函数
  7. A()
  8. {
  9. cout << "constructor" << endl;
  10. }
  11. // 析构函数
  12. ~A()
  13. {
  14. cout << "destructor" << endl;
  15. }
  16. // 拷贝构造函数
  17. A(A &)
  18. {
  19. cout << "copy constructor" << endl;
  20. }
  21. };
  22. A fun(A &a)
  23. {
  24. return a;
  25. }
  26. int main()
  27. {
  28. A a;
  29. fun(a);
  30. return 0;
  31. }

    结果为:

 

constructor
copy constructor
destructor
destructor

  1. #include <iostream>
  2. using namespace std;
  3. class A
  4. {
  5. public:
  6. // 构造函数
  7. A()
  8. {
  9. cout << "constructor" << endl;
  10. }
  11. // 析构函数
  12. ~A()
  13. {
  14. cout << "destructor" << endl;
  15. }
  16. // 拷贝构造函数
  17. A(A &)
  18. {
  19. cout << "copy constructor" << endl;
  20. }
  21. };
  22. A &fun(A &a)
  23. {
  24. return a;
  25. }
  26. int main()
  27. {
  28. A a;
  29. fun(a);
  30. return 0;
  31. }

    结果为:

 

constructor
destructor

    由此可见,对于ADT数据类型而言,用引用做函数参数或返回值,都能提高效率。

 

    

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载