Chinaunix首页 | 论坛 | 博客
  • 博客访问: 300391
  • 博文数量: 82
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 490
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-13 10:58
文章分类

全部博文(82)

文章存档

2018年(2)

2017年(9)

2016年(71)

我的朋友

分类: C/C++

2016-10-06 12:56:48


1.
简单异常的例子

1.1 成功捕获异常处理
  异常的语法包括
try{}块和catch{}块,try块用于检测异常的发生,catch块用于捕获异常。每个异常的抛出都使用了throw语句,并伴随了一个值(可以是任何类型)一起返回。例如throw 1.1,则是抛出一个浮点数数据类型的异常。当抛出异常后,程序会一直后退,直到找到被try块包围的函数,然后接着在try块后边找catch块,如果catch的括号参数中的类型和抛出的异常类型相同,则表示异常被捕获,并执行catch块中的代码。如果catch中没有与抛出的类型相同的参数,则表示异常未被捕获,这时程序将调用terminal()函数,异常终止程序。下边是一个简单的捕获异常的例子:

1.1

  1. #include <iostream>
  2. using std::cout;
  3. using std::endl;

  4. void job()
  5. {
  6.     cout << "job" << endl;
  7.     throw 1.1; //抛出浮点类型异常,抛出的异常是一个拷贝
  8.     //throw "ss"; //抛出字符串类型异常
  9.     //throw 5; //抛出整形字符串异常
  10. }

  11. int main()
  12. {
  13.     try {
  14.         job();
  15.     }
  16.     catch (int n) {
  17.         cout << "1.1\n";
  18.     }
  19.     catch (char * s) {
  20.         cout << "1.2\n";
  21.     }
  22.     catch (...) {
  23.         cout << "1.3\n";
  24.     }
  25.     cout << "1.4\n";
  26.     return 0;
  27. }

输出:

  1. [root@192 ch-15]# ./main
  2. job
  3. 1.3
  4. 1.4

注意事项:

1)catch(…)中的表示捕获任意发生的异常。

2)try块和catch块的代码必须全部连续的写在一起,中间不能插入任何代码,否则编译不通过。

3)当异常被捕获之后,程序会接着被捕获的地方,向下继续执行代码,如例子中输出的1.4

1.2 捕获异常失败

如果catch中没有与抛出的类型相同的参数,则表示异常未被捕获,这时程序将调用terminal()函数,而terminal()函数最终会调用abort()函数,异常退出进程。

1.2

  1. #include
  2. using std::cout;
  3. using std::endl;
  4.  
  5. void job()
  6. {
  7.     cout << "job" << endl;
  8.     throw 1.1;
  9. }
  10.  
  11. int main()
  12. {
  13.     try {
  14.         job();
  15.     }
  16.     catch (char * s) {
  17.         cout << "2.1\n";
  18.     }
  19.     cout << "2.2\n";
  20.     return 0;
  21. }

输出:

  1. [root@192 summary]# ./main
  2. job
  3. terminate called after throwing an instance of 'double'
  4. Aborted (core dumped)

注意事项:

1)cout << "2.2\n"; 未被执行,原因在于程序调用abort()函数后将立即终止运行。

 参考资料:

 

2. 重载terminate函数

2.1 重载terminate函数

  当捕获异常失败时,调用的terminate()函数是可以重载的,方法是调用set_terminate()函数,该函数位于头文件中,且重载的函数必须是无参数无返回值的。重新设置terminate ()函数后,每次调用terminate ()函数时,就会调用重新设置的函数。

2.1

  1. #include <iostream>
  2. #include <exception>
  3. using std::cout;
  4. using std::endl;

  5. void deal_terminate ()
  6. {
  7.     cout << "terminate" << endl;
  8.     std::abort(); //异常终止进程
  9. }

  10. void job()
  11. {
  12.     cout << "job" << endl;
  13.     throw 1.1;
  14. }

  15. int main()
  16. {
  17.     std::set_terminate(deal_terminate); //重载terminal()函数为deal_terminal()函数
  18.     try {
  19.         job();
  20.     }
  21.     catch (char * s) {
  22.         cout << "2.1\n";
  23.     }
  24.     return 0;
  25. }

输出:

  1. [root@192 summary]# ./main
  2. job
  3. terminate
  4. Aborted (core dumped)

注意事项:

1) 如果多次调用set_terminate()函数,则最后那一次调用才是有效的。

2) 如果例2.1deal_terminal()函数不调用abort()函数,将会发生什么呢?测试后发现,与以上输出结果相同,程序任然异常退出了。而且我重新在deal_terminal()函数中添加throw,抛出异常捕获任然不成功。这应该说明了,只要调用了terminate()函数,程序必然会被强制异常退出。

 参考资料:

 

3. 异常规范

3.1 throw()set_unexpected()

  throw定义在一个函数的参数后边,表示这个函数抛出的异常将受到限制。例如throw()表示这个函数不能抛出异常,若抛出了异常,则将调用unexpected()函数,而unexpected()函数会调用terminate()函数。和terminate()函数一样,unexpected()函数也可以被重载,设置重载的函数为set_unexpected()。但与terminate()函数不同的是,unexpected()的重载函数中可以重新抛出异常,有可能使得函数继续执行;而terminate()函数或其重载函数只要被调用,程序必然会异常终止。以下是使用throw()set_unexpected()的一个例子。

3.1

  1. #include <iostream>
  2. #include <exception>
  3. using std::cout;
  4. using std::endl;
  5.  
  6. void deal_terminate()
  7. {
  8.     cout << "terminate" << endl;
  9.     std::abort();
  10. }
  11.  
  12. void deal_unexpected()
  13. {
  14.     cout << "unexpected" << endl;
  15.     throw 3.3;
  16. }
  17.  
  18. void job() throw() //约定该函数不抛出异常
  19. {
  20.     cout << "job" << endl;
  21.     throw 5;
  22. }
  23.  
  24. int main()
  25. {
  26.     std::set_unexpected(deal_unexpected); //重载unexpected()函数
  27.     std::set_terminate(deal_terminate);
  28.     try {
  29.         job();
  30.     }
  31.     catch (int n) {
  32.         cout << "3.1\n";
  33.     }
  34.     catch (...) {
  35.         cout << "3.2\n";
  36.     }
  37.     cout << "3.3\n";
  38.     return 0;
  39. }
输出:
  1. [root@192 summary]# ./main
  2. job
  3. unexpected
  4. terminate
  5. Aborted (core dumped)

注意事项:

1)如果deal_unexpected()不抛出异常,则程序必然调用terminate()函数终止运行;反之,则有可能使程序继续运行。

参考资料:

 

3.2 noexcept

 noexceptthrow()的用法大致相同,指明函数不引发异常。若函数引发了异常,则直接调用terminate()函数异常终止进程,而不是unexpected()函数。下边这个例子说明了这点。

3.2

  1. #include <iostream>
  2. #include <exception>
  3. using std::cout;
  4. using std::endl;
  5.  
  6. void deal_terminate()
  7. {
  8.     cout << "terminate" << endl;
  9.     std::abort();
  10. }
  11.  
  12. void deal_unexpected()
  13. {
  14.     cout << "unexpected" << endl;
  15.     throw 3;
  16. }
  17.  
  18. void job() noexcept //noexcept
  19. {
  20.     cout << "job" << endl;
  21.     throw 3.3;
  22. }
  23.  
  24. int main()
  25. {
  26.     std::set_unexpected(deal_unexpected);
  27.     std::set_terminate(deal_terminate);
  28.     try {
  29.         job();
  30.     }
  31.     catch (int n) {
  32.         cout << "3.1\n";
  33.     }
  34.     catch (std::bad_exception) {
  35.         cout << "3.2\n";
  36.     }
  37.     catch (...) {
  38.         cout << "3.3\n";
  39.     }
  40.     cout << "3.4\n";
  41.     return 0;
  42. }

输出:

  1. [root@192 summary]# ./main
  2. job
  3. terminate //未调用unexpected()函数
  4. Aborted (core dumped)

注意事项:

1)noexcept指定的函数出现异常,则直接调用terminate()函数异常终止程序。

 

3.3 throw(int, double)

  如果在异常规范throw()中指明了类型,则表示该函数只接受该类型的异常抛出。若是其他异常,则同样调用unexcepted()函数。通常称未被指定抛出的异常未意外异常,以下是成功抛出一个异常的例子。

3.3

  1. #include <iostream>
  2. #include <exception>

  3. using std::cout;
  4. using std::endl;

  5. void deal_terminate()
  6. {
  7.     cout << "terminate" << endl;
  8.     std::abort();
  9. }

  10. void deal_unexpected()
  11. {
  12.     cout << "unexpected" << endl;
  13.     throw 3.3;
  14. }

  15. void job() throw(int, double) //约定该函数只抛出int和double类型异常
  16. {
  17.     cout << "job" << endl;
  18.     throw 5;
  19. }

  20. int main()
  21. {
  22.     std::set_unexpected(deal_unexpected); //重载unexpected()函数
  23.     std::set_terminate(deal_terminate);
  24.     try {
  25.         job();
  26.     }
  27.     catch (int n) {
  28.         cout << "3.1\n";
  29.     }
  30.     catch (...) {
  31.         cout << "3.2\n";
  32.     }
  33.     cout << "3.3\n";
  34.     return 0;
  35. }

输出:

  1. [root@192 summary]# ./main
  2. job
  3. 3.1
  4. 3.3

 

3.4 throw(bad_exception)

bad_exception类是由exception类派生的类,来自头文件中。如果异常规范throw中添加了bad_exception类型,又throw限制的函数抛出了意外异常,且set_unexpected()函数重载的unexpected()函数重新抛出了异常,则会得到以下两个效果。

1) 如果重载的unexpected()函数抛出的异常类型是throw中规定的类型,则抛出该类型异常。

2)如果重载的unexpected()函数抛出的异常类型不是throw中规定的类型,则抛出bad_exception类型异常。

3.4.1和例3.4.2分别演示了这两种情况。

3.4.1

  1. #include <iostream>
  2. #include <exception>

  3. using std::cout;
  4. using std::endl;

  5. void deal_terminate()
  6. {
  7.     cout << "terminate" << endl;
  8.     std::abort();
  9. }

  10. void deal_unexpected()
  11. {
  12.     cout << "unexpected" << endl;
  13.     throw 3.3; //抛出不是job()函数规定的类型
  14. }

  15. void job() throw(int, std::bad_exception)
  16. {
  17.     cout << "job" << endl;
  18.     throw 3.3; //意外异常
  19. }

  20. int main()
  21. {
  22.     std::set_unexpected(deal_unexpected);
  23.     std::set_terminate(deal_terminate);
  24.     try {
  25.         job();
  26.     }
  27.     catch (int n) {
  28.         cout << "3.1\n";
  29.     }
  30.     catch (std::bad_exception) {
  31.         cout << "3.2\n";
  32.     }
  33.     catch (...) {
  34.         cout << "3.3\n";
  35.     }
  36.     cout << "3.4\n";
  37.     return 0;
  38. }

输出:

  1. [root@192 summary]# ./main
  2. job
  3. unexpected
  4. 3.2 //抛出了bad_exception类型异常
  5. 3.4

3.4.2

  1. #include <iostream>
  2. #include <exception>

  3. using std::cout;
  4. using std::endl;

  5. void deal_terminate()
  6. {
  7.     cout << "terminate" << endl;
  8.     std::abort();
  9. }

  10. void deal_unexpected()
  11. {
  12.     cout << "unexpected" << endl;
  13.     throw 3; //抛出的是job()函数规定的类型
  14. }

  15. void job() throw(int, std::bad_exception)
  16. {
  17.     cout << "job" << endl;
  18.     throw 3.3; //意外异常
  19. }

  20. int main()
  21. {
  22.     std::set_unexpected(deal_unexpected);
  23.     std::set_terminate(deal_terminate);
  24.     try {
  25.         job();
  26.     }
  27.     catch (int n) {
  28.         cout << "3.1\n";
  29.     }
  30.     catch (std::bad_exception) {
  31.         cout << "3.2\n";
  32.     }
  33.     catch (...) {
  34.         cout << "3.3\n";
  35.     }
  36. cout << "3.4\n";
  37. return 0;
  38. }

输出:

  1. [root@192 summary]# ./main
  2. job
  3. unexpected
  4. 3.1 //抛出了int类型异常
  5. 3.4

注意事项:

1)要成功处理意外异常必须满足两点,一是在throw中加入bad_exception规范,二是必须在重载的unexpected()函数中使用throw抛出异常。

2)如果unexpected()重载函数中,直接使用了throw;语句,并未指明抛出的数据类型(如throw 5),则抛出的数据和进入unexpected()重载函数前的异常数据相同。 

参考资料:

 

4. exception

4.1 logic_errorruntime_error

  exception类是异常处理的基类,在头文件中,几乎所有处理异常的类都是由exception类派生出来的。logic_error类和runtime_error类就是由exception类派生出来的,在头文件中,它们分别派生出了domain_error, future_error, length_error, invalid_argument, out_of_range类和overflow, range_error, system_error, underflow_error类。这些类只是名字不一样,内部实现相同。它们接收string对象作为参数,并使用what()方法返回c字符串。如果需要的话,也可以自己从exception派生出需要的异常类,不过构造函数和what()方法都需要自己实现。以下是使用logic_error和自己派生异常类的方法。

4.1.1

  1. #include <iostream>
  2. #include <exception>
  3. #include <stdexcept>

  4. using std::cout;
  5. using std::endl;

  6. void job()
  7. {
  8.     cout << "job" << endl;
  9.     throw std::out_of_range("out_of_range"); //使用out_of_range抛出异常
  10. }

  11. int main()
  12. {
  13.     try {
  14.         job();
  15.     }
  16.     catch (int n) {
  17.         cout << "4.1\n";
  18.     }
  19.     catch (std::out_of_range & ou) {
  20.         cout << ou.what() << "4.2\n";
  21.     }
  22.     catch (std::logic_error & lo) {
  23.         cout << lo.what() << "4.3\n"; //打印从异常中返回的数据
  24.     }
  25.     catch (...) {
  26.         cout << "4.4\n";
  27.     }
  28.     cout << "4.5\n"; return 0;
  29. }

输出:

  1. [root@192 summary]# ./main
  2. job
  3. out_of_range4.2 //捕获到out_of_range类异常
  4. 4.5

4.1.2

  1. #include <iostream>
  2. #include <exception>
  3. #include <stdexcept>

  4. using std::cout;
  5. using std::endl;

  6. //自己派生的异常类
  7. class my_exception : public std::exception
  8. {
  9. private:
  10.     std::string si;
  11. public:
  12.     explicit my_exception(const std::string & s) : si(s){};
  13.     const char* what() const noexcept { return si.c_str(); }
  14. };

  15. void job()
  16. {
  17.     cout << "job" << endl;
  18.     throw my_exception("my_exception"); //抛出异常

  19. }

  20. int main()
  21. {
  22.     try {
  23.         job();
  24.     }
  25.     catch (int n) {
  26.         cout << "4.1\n";
  27.     }
  28.     catch (my_exception & ou) { //捕获异常
  29.         cout << ou.what() << "4.2\n";
  30.     }
  31.     catch (std::exception & ou) {
  32.         cout << ou.what() << "4.2\n";
  33.     }
  34.     catch (...) {
  35.         cout << "4.4\n";
  36.     }
  37.     cout << "4.5\n";
  38.     return 0;
  39. }

输出:

  1. [root@192 summary]# ./main
  2. job
  3. my_exception4.2
  4. 4.5

注意事项:

1) 如果要自己从exception中派生出异常类,则需要自己重写构造函数和what()函数。

2) 捕获层次类的顺序是从离祖先类最远的类开始写catch块,最后一个类因该是祖先类(基类)。

参考资料:

5. new异常检测

5.1 bad_alloc

  bad_alloc类直接由exception类派生出来,当new动态分配空间失败时,将抛出bad_alloc类型异常。具体看例5.1.1

5.1.1

  1. #include <iostream>
  2. #include <exception>
  3. #include <stdexcept>

  4. using std::cout;
  5. using std::endl;

  6. int main()
  7. {
  8.     try {
  9.         while (1) {
  10.             int * p = new int[9999]; //一直消耗内存
  11.         }
  12.     }
  13.     catch (std::bad_alloc & ba) {
  14.         cout << ba.what() << "5.1\n";
  15.     }
  16.     cout << "5.2\n";
  17.     return 0;
  18. }

输出:

  1. [root@192 summary]# ./main
  2. std::bad_alloc5.1 //捕获到bad_alloc异常
  3. 5.2

参考资料:

 

5.2 nothrow

  c++提供了一种处理new的选项,即当动态分配空间失败时不抛出异常,而是返回空指针。这样的前提是在new后边添加上nothrow,请看下边一个例子。

5.2.1

  1. #include <iostream>
  2. #include <exception>
  3. #include <stdexcept>

  4. using std::cout;
  5. using std::endl;

  6. int main()
  7. {
  8.     try {
  9.         while (1) {
  10.             int * p = new (std::nothrow) int[9999]; //指定不抛出异常,只返回空指针
  11.             if (!p) {
  12.                 cout << "5.0\n";
  13.                 break;
  14.             }
  15.         }
  16.     }
  17.     catch (std::bad_alloc & ba) {
  18.         cout << ba.what() << "5.1\n";
  19.     }
  20.     cout << "5.2\n";
  21.     return 0;
  22. }

输出:

  1. [root@192 summary]# ./main
  2. 5.0 //返回空指针
  3. 5.2

参考资料:

 

6. RTTI(运行阶段类型检测)

6.1 dynamic_cast

  rtti是在动态运行代码时进行类型识别,只适用于包含虚函数的类dynamic_cast是一个能使指向基类的指针转换成指向派生类的指针的运算符,就是向上类型转换。如果转换失败,则返回空指针。dynamic_cast除了实现指针间转换外,还可以实现引用之间的转换。不过当转换失败时,则是抛出bad_cast类型的异常,也是有exception类派生来,定义在头文件>以下是使用dynamic_cast进行指针和引用转换类的例子。

6.1.1

  1. #include <iostream>
  2. #include <exception>
  3. #include <stdexcept>
  4. #include <typeinfo>
  5. using std::cout;
  6. using std::endl;

  7. int main()
  8. {
  9.     //class A { public: virtual ~A(){}}; //虚析构函数
  10.     class A { virtual void dump(){}}; //虚函数
  11.     class B : public A {};

  12.     //1.指针转换
  13.     A *p1 = new A;
  14.     A *p2 = new B;
  15.     
  16.     B * np1 = dynamic_cast<B *>(p1);
  17.     if (np1) {
  18.         cout << "6.0\n";
  19.     }
  20.     
  21.     B * np2 = dynamic_cast<B *>(p2);
  22.     if (np2) {
  23.         cout << "6.1\n";
  24.     }

  25.     //2.引用转换
  26.     A a1;
  27.     A & ya1 = a1;
  28.     try {
  29.         B & yb1 = dynamic_cast<B &>(ya1);
  30.     }
  31.     catch (std::bad_cast & ba) {
  32.         cout << ba.what() << endl;
  33.     }
  34.     cout << "6.2\n";
  35.     return 0;
  36. }

输出:

  1. [root@192 summary]# ./main
  2. 6.1
  3. std::bad_cast //引用转换失败,捕获异常
  4. 6.2

注意事项:

1) 要使dynamic_cast能转换成功,基类必须有虚函数,可以是虚析构函数,也可以是其它成员函数。因为dynamic_cast使用的条件必须是多态情况,即基类存在虚函数。 

参考资料:

 

6.2 typeid

  typeid可接受的参数为类名或结果为对象的表达式。typeid运算符返回type_info类型的引用,因此使用typeid(class).name(),可以得到类的字符串名称。由于type_info类型重载了==!=运算符,所以可以使用这些运算符对类型进行比较。例如存在类A,定义了A *a = new A,这时可以通过typeid(A) == typeid(*a)是否相等来判断a是否指向的是A类型。若a是空指针,则会抛出bad_taypeid类型异常,bad_taypeid类同样派生于exception类。

下边的例子演示这几项特性。

6.2.1

  1. #include <iostream>
  2. #include <exception>
  3. #include <stdexcept>
  4. #include <typeinfo>
  5. using std::cout;
  6. using std::endl;

  7. int main()
  8. {
  9.     class A { virtual void dump(){}};
  10.     class B : public A {};

  11.     A * p1 = new A;
  12.     A * p2 = new B;
  13.     
  14.     if (typeid(A) == typeid(*p2)) { //比较是否是同一个类型
  15.         cout << "typeid(A) == typeid(*p2)\n";
  16.     }
  17.     
  18.     if (typeid(B) == typeid(*p2)) {
  19.         cout << "typeid(B) == typeid(*p2)\n";
  20.     }
  21.     
  22.     cout << typeid(*p2).name() << endl; //输出类型名称
  23.     
  24.     A * p3 = NULL;
  25.     try {
  26.         typeid(*p3);
  27.     }
  28.     catch (std::bad_typeid & ba) { //捕获空类型异常
  29.         cout << ba.what() << endl;
  30.     }
  31.     
  32.     cout << "6.0\n";
  33.     return 0;
  34. }

输出:

  1. [root@192 summary]# ./main
  2. typeid(B) == typeid(*p2)
  3. Z11summary_6_1vE1B //类型名称,链接符号
  4. std::bad_typeid //类型指针为空时,捕获到异常
  5. 6.0

注意事项:

1) 不管类指针a本身是什么类型,typeid(*a)得到的类型始终是a指向的地址空间最开始定义时的类型。就好比上例中的A * p2 = new B,则typeid(*p2)的类型就应该是B类型,而不是A类型。

参考资料:

 

7. 类型转换运算符

7.1 const_cast

  c++特有的类型转换运算符有dynamic_cast, const_cast, static_cast, reinterpret_cast四种,dynamic_cast前边已经讲过了,这里说一下const_cast的作用。const_cast可以去除变量的constvolatile属性,且只能是指针或引用。

下边的例子演示了这种特性。

7.1.1

  1. #include <iostream>
  2. using std::cout;
  3. using std::endl;

  4. int main()
  5. {
  6.     const int a = 99;
  7.     int * b = const_cast<int *>(&a);
  8.     int & c = const_cast<int &>(a);
  9.     
  10.     *b = 50;    
  11.     cout << "a: " << a << endl;
  12.     cout << "b: " << *b << endl;
  13.     
  14.     c = 40;
  15.     cout << "a: " << a << endl;
  16.     cout << "c: " << c << endl;
  17.     return 0;
  18. }

输出:

  1. [root@192 summary]# ./main
  2. a: 99 //编译器优化导致cout直接输出a的值始终为99
  3. b: 50
  4. a: 99
  5. c: 40

注意事项:

1) 以上例子存在的一个问题是,输出a变量时的值始终为初始化的值99,而它的引用和指针确实修改了a的值。原因应该是编译器的优化,当编译时,程序始终认为a是一个常量,所以将后边的所有a变量直接替换成了99。以上只是一种猜测,也可能存在其它原因。

参考资料:

 

7.2 static_cast

  当两种类型AB中的A能隐式的转换成B,但B不能隐式地转换成A时,这时可以用static_castB转换成A。就好比基类和派生类中,基类可以显示但不能隐式地转换成派生类一样,下边的例子说明了这点。

7.2.1

  1. #include <iostream>
  2. using std::cout;
  3. using std::endl;

  4. int main()
  5. {
  6.     class A { virtual void dump(){}};
  7.     class B : public A {};

  8.     A * p1 = new A;
  9.     B * p2 = static_cast<B *>(p1);
  10.     
  11.     cout << p1 << endl;
  12.     cout << p2 << endl;
  13.     return 0;
  14. }

输出:

  1. [root@192 summary]# ./main
  2. 0x9583008
  3. 0x9583008

注意事项:

1) static_cast不能去掉const属性,即不能将带有const的类型转换成另一种类型。

参考资料:

 

7.3 reinterpret_cast

  reinterpret的使用范围比较广,首先它可以实现任意两种指针类型之间的转换,即时是两个毫不相关的类型;其次也能将指针的值转换成整型值,只要该整型能存储指针的大小。

7.3.1

  1. #include <iostream>
  2. using std::cout;
  3. using std::endl;

  4. int main()
  5. {
  6.     //1.实现和static_cast相同功能
  7.     class A { virtual void dump(){}};
  8.     class B : public A {};

  9.     A * p1 = new A;
  10.     B * p2 = reinterpret_cast<B *>(p1);
  11.     B * p3 = static_cast<B *>(p1);
  12.     
  13.     cout << "p1: " << p1 << endl;
  14.     cout << "p2: " << p2 << endl;
  15.     cout << "p3: " << p3 << endl;

  16.     //2.转换两个不同类型的指针
  17.     int * p4 = reinterpret_cast<int *>(p1);
  18.     cout << "p4: " << p4 << endl;
  19.     
  20.     //3.将指针转换成整型值
  21.     int p5 = reinterpret_cast<int>(p1);
  22.     cout << "p5: " << std::hex << "0x" << p5 << endl;
  23.     return 0;
  24. }

输出:

  1. [root@192 summary]# ./main
  2. p1: 0x9efd008
  3. p2: 0x9efd008
  4. p3: 0x9efd008
  5. p4: 0x9efd008
  6. p5: 0x9efd008

参考资料:


阅读(1378) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~