C ++在函数中分配动态内存 - 新手问题

时间:2009-12-18 23:15:17

标签: c++ memory function dynamic pointers

我正在调查内存泄漏,从我看到的,问题看起来像这样:

int main(){
    char *cp = 0;
    func(cp);
    //code
    delete[] cp;
}

void func(char *cp){
    cp = new char[100];
}

在//代码注释中,我希望cp指向已分配的内存,但它仍然是一个空指针,这意味着我永远不会删除内存。我在做什么呢?

7 个答案:

答案 0 :(得分:18)

您正在为cp分配已分配内存的值。但是,这是堆栈中的变量:main cp的副本! cp是您所在职能的本地。

你想要的是一个参考:

void func(char *& cp)

这将别名cp作为传入的参数。

答案 1 :(得分:12)

void func(char *cp){
    cp = new char[100];
}

在这个函数中,char * cp是一个“指针 copy 传递”,这意味着它们指向相同的内存地址,但它们不是<强>相同指针。当您更改内部指针,使其指向其他位置时,已传递的原始指针将始终指向0。

答案 2 :(得分:6)

参数cp是函数的局部变量 - 更改它不会改变函数外的任何内容。编写函数的更好方法是:

char * func(){
    return new char[100];
}

不要直接处理你的问题,但你应该使用std :: string和std :: vector而不是动态分配的数组。

答案 3 :(得分:1)

您传递的是cbuf,而不是cp

答案 4 :(得分:1)

该功能仅更改cp的COPY。改为使用引用。

答案 5 :(得分:1)

尽管引用在提供直观抽象方面非常出色,但通过C ++ 11 rvalue引用进一步增强以允许函数链(以及其他深奥编码),可以证明它们提供了任何安全性(即why is a reference considered safer than a pointer) 有些情况下,最好使用指向指针函数参数的指针来解决上述问题。 特别是当需要在ansi c和c ++中维护类似的代码库时。

#include <iostream>

using namespace std;

void func(char ** cp) {
    *cp = new char[100];
    //do something useful
    (*cp)[0] = 'A';
}

void func(char *& cp) {
    cp = new char[100];
    //do something useful
    cp[0] = 'B';
}

int main(int argc, char** argv) {
    char * cp;
    //pointer to pointer
    func(&cp);
    cout << "Index 0 : " << cp[0] << '\n' << flush;
    delete[] cp; //remember to delete!!
    //pointer to ref
    func(cp);
    cout << "Index 0: " << cp[0] << '\n' << flush;
    delete[] cp;
    return 0;
}

当然,超出安置功能范围的内存资源的处理违反了RAII。

答案 6 :(得分:0)

正如GMan和Neil所说,为了工作,你必须将func改为:

char* func();

void func(char*& p);

这将解决您当前的问题。

然而,存在维护问题。在任何一种情况下,func都会返回一个指针。 func的用户不清楚的是返回的指针必须被删除。因此,除非100%必要,否则通常避免使用此构造。更确切地说:

  1. 帮助用户分配正确的内存量,然后将其传递给func
  2. 使用对象存储分配的内存。然后,对象可以在破坏时删除字符数组。
  3. 因此,对于C ++代码,我建议:

    
    class CBuf
    {
    public
        CBuf() 
        {
            iBuf = new char[100];
        }
        ~CBuf
        {
            delete[] iBuf;
        }
        char* func()
        {
            //do stuff;
            return iBuf;
        }
    private:
        char* iBuf;
    };
    
    int main()
        {
        CBuf cb;
        char* mychar = cb.func();
        //do stuff with character array
    
        //destructor gets called here because cb goes out of scope
        }
    

    但是,特别是在C编程中,使用某种排序函数创建数组可能是100%必需的。因此,在C编程中,您可以使用CreateCBufDestroyCBuf函数替换析构函数。通过这种方式,库的用户将知道返回的缓冲区需要被销毁。