zoukankan      html  css  js  c++  java
  • 编程练习之数组与指针

    数组与指针

    阅读如下代码,为何出错。

     1 int main() {  
     2     char a[] = { "I am a bad boy" };  
     3     char * pA = new char[ sizeof( a ) ];  
     4     pA = a;  
     5       
     6     for ( size_t i = 0; i < sizeof( a ); ++i ) {  
     7         std::cout << *pA << std::endl;  
     8         ++pA;  
     9     }  
    10     delete [] pA;  
    11     pA = NULL;  
    12     return 0;  
    13 }

    我们把那段魔术字符串命名为x。

    第一步我们将字符串x存入了栈空间;第二步我们试图在堆空间申请一块可以正好存放x的的内存。以上两步都做得很对,但第三步大有问题。

    本意是企图将x复制入堆内存中,但实际操作的结果是将指针指向了原x所在的栈空间。这将导致一个内存泄漏。(要注意的是string类的等于号能够赋值是因为操作符的重载)。接下来是遍历整个字符串,运行结果仿佛复制成功了一样,但实际上你是在遍历存在于栈空间的x。遍历的过程中还不断修改指针指向的值,因为分配字符串时最后会自动添加一个空字符串(等价于NULL或0),指针最终指向了栈空间的x末尾的空字符串处。企图释放栈空间导致的爆炸就更不用说了。

    代码如何修改才正确呢?

     1 int main() {  
     2     char a[] = { "I am a bad boy" };  
     3     char * pA = new char[ sizeof( a ) ]; 
     4     strcpy( pA, a );    
     5     for ( size_t i = 0; i < sizeof( a ); ++i ) {  
     6         std::cout << *( pA + i );  
     7     }  
     8     delete [] pA;  
     9     pA = NULL;  
    10     return 0;  
    11 }  

    将字符串拷贝到堆内存分配的空间中,需要用到c函数strcpy,将值拷贝过去。你也可以将x的每一个字符赋值过去。注意,千万尽量不要改变指向堆内存首个位置的指针,如果你有把握还原回去的话。释放一定要从堆内存首部分开始,不然也会导致爆炸。

    期间你有可能会忽略这些问题。

    (1)

    1 ++pA;

    上面已经提到过了,没有把握释放的是首位的话尽量不要改变指针的指向。你可以使用指针的偏移或数组下标来进行操作

    (2)

    1 char * pA = new char[ strlen( a ) ]; 

    要注意strlen不计空字符的,因此堆内存分配时中会少一个存放空字符的空间,导致很多函数不能在这段字符结束时停止读取。

    1 char * pA = new char[ strlen( a ) + 1 ]; 

    多分配一个即可,或你可以使用sizeof(注意 sizeof 指向堆内存指针 为指针的大小)。

    (3)

    你可能会这样释放数组堆内存。

    1 delete pA;  

    编译运行,没有任何问题。但这是一个未定义行为(UB),在不同的平台或编译器下运行结果可能不同,总之这是一个潜在的危险操作,你应该让自己严格使用delete[]去释放数组堆内存。

    后记:

    提到了string重载的等号。对于熟悉C/C++的人在这方面不会有任何问题,但对于初学者这可能确实不太好理解和弄懂。我一直不使用重载操作符或许和这也有关系吧。

  • 相关阅读:
    JQuery高级
    Filter&Listener
    关于用户信息的一个综合案例
    JSP,EL和JSTL
    Cookie和Session
    Request和Response
    Servlet和HTTP请求协议
    Tomcat
    xml
    数组模拟堆
  • 原文地址:https://www.cnblogs.com/PROJECT-IDOLPROGRAM/p/5097344.html
Copyright © 2011-2022 走看看