不同的输出取决于删除

时间:2016-08-04 13:36:05

标签: c++ function pointers parameters

我有这段代码:

#include <iostream>
using namespace std;
char* pass(char* p){
    char* a = new char[10];
    a[0] = 'S';
    a[1] = 'e';
    a[2] = 'r';
    a[3] = 'g';
    a[3] = 'e';
    a[3] = 'y';
    a[4] = '\0';
    p = a;
    //delete [] a;
    return p;
}
int main(int argc,char* argv[]){
    char* p1 = new char[1000];
    p1[0] = 'G';
    p1[1] = 'e';
    p1[2] = 'r';
    p1[3] = 'y';
    p1[4] = '\0';
    char* p2 = p1;
    cout << p2 << endl;
    cout << pass(p2) << endl;
    delete [] p1;
}

,输出为:

Gery
Sery

但如果我取消注释delete [] a行 我得到了这个输出:

Gery
ê§É

为什么?

3 个答案:

答案 0 :(得分:2)

在此功能中

char* pass(char* p){
    char* a = new char[10];
    a[0] = 'S';
    a[1] = 'e';
    a[2] = 'r';
    a[3] = 'g';
    a[3] = 'e';
    a[3] = 'y';
    a[4] = '\0';
    p = a;
    //delete [] a;
    return p;
}

参数是函数的局部变量。退出该功能后,它将被销毁。

您可以通过以下方式想象函数及其调用

pass(p2);

char* pass(/*char* p*/){
    char* p = p2;
    char* a = new char[10];
    a[0] = 'S';
    a[1] = 'e';
    a[2] = 'r';
    a[3] = 'g';
    a[3] = 'e';
    a[3] = 'y';
    a[4] = '\0';
    p = a;
    //delete [] a;
    return p;
}

如您所见,原始指针p2将不会在函数中更改。该函数更改其声明为参数的局部变量p

如果取消注释delete语句,则返回值指向的内存将被删除,返回的指针将无效。在这种情况下,由于语句

,程序具有未定义的行为
cout << pass(p2) << endl;

尝试使用函数的返回值访问已删除的内存。

因此没有意义返回指向已删除内存的指针。

您想要做的事情可以通过三种方式实现

第一个是将参数声明为参考

char* pass(char* &p){
           ^^^^^^^^
    char* a = new char[10];
    a[0] = 'S';
    a[1] = 'e';
    a[2] = 'r';
    a[3] = 'g';
    a[3] = 'e';
    a[3] = 'y';
    a[4] = '\0';
    p = a;
    return p;
}

并调用函数

cout << pass(p2) << endl;

第二个是将参数声明为指向间接接受原始指针的指针

char* pass(char* *p){
           ^^^^^^^^
    char* a = new char[10];
    a[0] = 'S';
    a[1] = 'e';
    a[2] = 'r';
    a[3] = 'g';
    a[3] = 'e';
    a[3] = 'y';
    a[4] = '\0';
    *p = a;
    ^^^^^^^^
    return *p;
    ^^^^^^^^^^
}

并调用函数

cout << pass(&p2) << endl;

最后你可以简单地将返回的值分配给原始指针。例如

char* pass(char* p){
    char* a = new char[10];
    a[0] = 'S';
    a[1] = 'e';
    a[2] = 'r';
    a[3] = 'g';
    a[3] = 'e';
    a[3] = 'y';
    a[4] = '\0';
    p = a;
    return p;
}

并将函数调用为

cout << ( p2 = pass(p2) ) << endl;

虽然在这种情况下参数已过时。

在任何情况下,您都应该删除程序末尾的已分配内存,如

delete [] p2;

答案 1 :(得分:1)

p = a

不会复制值。

您正在寻找的可能是:

memcpy(p, a, 10*sizeof(char));

答案 2 :(得分:0)

因为您的未注释行会释放您返回的内存,而您的编译器(可能作为调试辅助工具)会覆盖已释放的内存。

您的p按值传递,因此p = a;实际上并未在主内部更改p1。您基本上初始化内存,删除它,然后返回指向已删除内存的指针。

如果没有额外删除,您只需泄漏该内存。