C++ 什么';这是使用C++;具有函数的新运算符?

C++ 什么';这是使用C++;具有函数的新运算符?,c++,function,scope,new-operator,C++,Function,Scope,New Operator,这是一个长的。我有一个从磁盘加载一些图像数据的函数。我尝试过三种不同的方法,其中一种不起作用,我想知道最聪明的方法是什么 方法1: 我曾经对它进行过设置,以便加载的数据是函数的参数,这似乎需要在函数外部为它分配空间,然后向分配的空间传递指针。这需要提前知道图像的大小,因此必须先使用辅助函数来获得图像的宽度和高度。下面是一个例子 优点:在调用代码中更明确地表示正在分配内存,因此应该删除 缺点:需要提前知道图像大小 // Data allocated outside the image, alloc

这是一个长的。我有一个从磁盘加载一些图像数据的函数。我尝试过三种不同的方法,其中一种不起作用,我想知道最聪明的方法是什么

方法1:

我曾经对它进行过设置,以便加载的数据是函数的参数,这似乎需要在函数外部为它分配空间,然后向分配的空间传递指针。这需要提前知道图像的大小,因此必须先使用辅助函数来获得图像的宽度和高度。下面是一个例子

优点:在调用代码中更明确地表示正在分配内存,因此应该删除

缺点:需要提前知道图像大小

// Data allocated outside the image, allocated space passed to function. This works.
// Notice that width & height are passed to the function. 
size=(*width)*(*height);
image  = new unsigned char[size];

void read_pgm(unsigned char *image, char *file_name, int width, int height){

    // Code to read sizeof(char)*width*height bytes of data from the file into image

}
方法2:

我认为让函数分配自己的数据会很好,这样我就不需要传递它的大小。如果我试图在函数中为它分配空间,它似乎在函数结束后丢失了。在下面的例子中,函数
read_pgm
运行良好,但是如果我试图将该数据写入另一个文件,我的代码就会崩溃

优点:不需要提前知道图像大小,不需要在调用代码中分配数据

缺点:不起作用。另外,如果是这样的话,如果我没有清除函数外部的映像,在循环中重复调用它会导致内存泄漏吗

// Data allocated inside the image for a pointer passed to the function. This doesn't work.
void read_pgm(unsigned char *image, char *file_name, int *width, int *height){

    size=(*width)*(*height);
    image  = new unsigned char[size];

    // Code to read the data from the file into image

}
方法3:

在这里,数据再次在函数中分配,但作为返回项返回。这是可行的,也就是说,我可以将数据写入另一个图像。我不明白为什么这是可行的,而方法2却不行

优点:与方法2相同

缺点:与方法2相同,只是目前有效

// Data allocated in the function, and returned. This works.
unsigned char* read_pgm(char *file_name, int *width, int *height){

    // Allocate data for the image
    size=(*width)*(*height);
    image  = new unsigned char[size];

    // Code to read the data from the file into image

    return image; // Return pointer to the data
}
因此,我的问题是:

  • 在这种情况下,将函数设置为自己分配空间,这样调用代码就不需要提供图像大小,这是否更明智?或者,在函数外部进行分配,作为在某个时刻需要在映像上调用delete的提醒,是否更明智。或者我认为这需要做是错误的?似乎在循环中调用方法2或方法3会导致内存泄漏

  • 为什么方法2不起作用

  • 谢谢

    对问题2的答复 为了使它工作,您必须传递指针的引用

    unsigned char * & image
    
    否则,您将分配内存,并且传递的指针的副本将指向它。原始指针对象不会更改

    对问题1的答复 听说过吗


    智能指针可以用来自行操作内存。如果你不想出于某种莫名其妙的原因使用智能指针,比如伪优化,那么我认为你自己描述了所有方法的优缺点——总是有权衡的。由您决定方法2不起作用,因为您正在按值传递指针,并在本地覆盖该值,因此函数外部指针的值不会更改。您可以通过引用或通过向指针传递指针来修复此问题

    至于另一个问题:这实际上只是一个明确记录谁有责任删除分配的数据的问题。(顺便说一下:是的,你应该解除分配,否则你会泄漏)。在许多API中,您将在文档中看到:“调用者有责任删除此函数”或“调用其他函数删除分配的数据”

    消除这种所有权顾虑的一个好方法是使用智能指针(正如Armen所建议的)。

    “2.为什么方法2不起作用?”

    因为您是通过副本而不是引用传递指针。您传入一个指针,然后使用
    new
    调用迅速重新初始化该指针指向的位置。当达到函数的范围时,局部变量
    image
    的寿命也就达到了,所有可爱的新存储都到哪里去了

    您真正想要做的(在本例中)是传递对指针的引用或指向指针的指针,以便可以更改所传递参数的值(本例中为指针),并使该更改在函数范围之外可见

    void read_pgm(unsigned char **image, char *file_name, int *width, int *height)
    {      
        size=(*width)*(*height);     
        (*image)  = new unsigned char[size];      
    
        // Code to read the data from the file into image  
    } 
    

    如果你想知道聪明的方法,那么答案必须是“以上都没有”。聪明的方法?使用向量。这就是它的目的。因为直接使用
    new
    很糟糕。管理你自己的记忆范围很糟糕。我们有这方面的课程。和字符串的
    char*
    ?至少将其设置为
    常量字符*
    <代码>常量标准::字符串&更好。我还必须问-你试图读取的图像格式是什么,它不以文件格式存储图像的宽度和高度?在我看来,你最好还是从文件中读出来

    std::vector<unsigned int> void ReadImage(const std::string& filename, int width, int height) {
        std::vector<unsigned int> imageData(width * height);
        // Read here from filestream
    }
    
    std::vector<unsigned int> imageData = ReadImage("ohai.png", 1000, 600);
    
    std::vector void ReadImage(常量std::字符串和文件名、整型宽度、整型高度){
    std::矢量图像数据(宽度*高度);
    //阅读这里的文件流
    }
    std::vector imageData=ReadImage(“ohai.png”,1000600);
    

    您需要了解-const correction、RAII和标准库。

    您当前所做的一切都会导致内存泄漏,因为您从未删除任何内容

    首先,是的,使尺寸可变。第二,返回指向新分配的堆存储的指针并记住在调用者中删除它,或者返回智能容器对象

    一个
    std::vector
    会很好地:

    std::vector<unsigned char> get_image(const std::string & filename, size_t & width, size_t & height)
    {
      // determine width and height
    
      /* ... */
    
      std::vector<unsigned char> result(width * height, 0);
    
      // read into &result[0], vector guarantees contiguous storage
    
      return result;
    }
    
    std::vector get\u image(常量std::字符串和文件名、大小和宽度、大小和高度)
    {
    //确定宽度和高度
    /* ... */
    标准::矢量结果(宽度*高度,0);
    //读入结果[0],向量保证连续存储(&R)
    返回结果;
    }
    
    事实上,这本书中有一个关于这些问题的非常好的章节

    正如您所说,最大的问题是确保内存的分配方式不会泄漏。C++有很多便利的工具来做,这是最明显的。
     {
         MyData *md = new MyData(args);
    
         doSomething(md);
    
     }