在堆上分配内存的函数原型(C/C++)

我对C很新,所以这可能是一个初学者的问题.它认为做某事的“适当”风格我怀疑是相当普遍的.

我正在编写一个函数,在执行其职责时,在堆上分配内存以供调用者使用.我很好奇这个函数的原型应该是什么样子.现在我有:

int f(char** buffer);

要使用它,我会写:

char* data;
int data_length = f(&data);
// ...
delete[] data;

但是,我正在向指针传递指针的事实让我觉得我可能做错了.

有人关心开导我吗?

解决方法

在C中,这或多或少是合法的.

在C中,函数通常不应该这样做.您应该尝试使用RAII来保证内存不会泄露.

现在你可能会说“它会如何泄漏内存,我只是在那里调用delete [!”,但是如果在//行引发异常怎么办?

根据功能的确切功能,您可以考虑多种选择.一个显而易见的是用向量替换数组:

std::vector<char> f();

std::vector<char> data = f();
int data_length = data.size();
// ...
//delete[] data;

现在我们不再需要显式删除,因为向量是在堆栈上分配的,当析构函数超出范围时会调用它的析构函数.

我应该在回应评论时提到,上述内容意味着载体的副本,这可能是昂贵的.如果f函数不是太复杂,大多数编译器会优化该副本,这样就可以了. (如果不经常调用该函数,则无论如何开销都无关紧要).但是如果没有发生这种情况,你可以通过引用将空数组传递给f函数,并将f数据存储在其中,而不是返回一个新的向量.

如果返回副本的性能是不可接受的,另一种选择是完全解耦容器的选择,而是使用迭代器:

// definition of f
template <typename iter>
void f(iter out);

// use of f
std::vector<char> vec;
f(std::back_inserter(vec));

现在可以使用通常的迭代器操作(* out用于引用或写入当前元素,out用于将迭代器向前移动到下一个元素) – 更重要的是,所有标准算法现在都可以使用.例如,您可以使用std :: copy将数据复制到迭代器.这是标准库通常选择的方法(即,这是一个好主意;))当函数必须返回一系列数据时.

另一种选择是让你自己的对象负责分配/解除分配:

struct f { // simplified for the sake of example. In the real world,it should be given a proper copy constructor + assignment operator,or they should be made inaccessible to avoid copying the object
  f(){
    // do whatever the f function was originally meant to do here
    size = ???
    data = new char[size];
  }
  ~f() { delete[] data; }

int size;
char* data;
};

f data;
int data_length = data.size;
// ...
//delete[] data;

而且我们不再需要显式删除,因为分配是由堆栈上的对象管理的.后者显然是更多的工作,并且有更多的错误空间,因此如果标准的矢量类(或其他标准库组件)完成工作,则更喜欢它们.此示例仅在您需要根据您的情况定制的内容时使用.

C中的一般经验法则是“如果你在RAII对象之外写一个删除或删除[],那你就错了.如果你在RAII对象外写一个新的或者新的[],你做错了,除非结果立即传递给智能指针“

相关文章

文章浏览阅读315次。之前用C语言编过链表,这几天突然想用C+...
文章浏览阅读219次。碰到问题就要记录下来,防止遗忘吧。文章...
文章浏览阅读1.8k次,点赞11次,收藏37次。因为自己对决策树...
文章浏览阅读492次。C++ 设计模式之策略模式
文章浏览阅读683次。我也算是个C++的小白,对于C++中的谓语我...
文章浏览阅读225次。又看了一遍操作符的东西,感觉之前对操作...