我看到在c++中有多种方法来分配和释放数据,我明白,当你调用malloc时你应该叫自由,当你使用新的操作符应与删除和对它是错误的把两个调用free()(例如,创建新的操作符),但是我不清楚我应该使用malloc / free,当我在现实世界中应该使用新的/删除程序。
如果你是c++专家,请告诉我你在这方面遵循的任何经验法则或惯例。
我看到在c++中有多种方法来分配和释放数据,我明白,当你调用malloc时你应该叫自由,当你使用新的操作符应与删除和对它是错误的把两个调用free()(例如,创建新的操作符),但是我不清楚我应该使用malloc / free,当我在现实世界中应该使用新的/删除程序。
如果你是c++专家,请告诉我你在这方面遵循的任何经验法则或惯例。
当前回答
malloc和new有一个很大的区别。Malloc分配内存。这对于C语言来说很好,因为在C语言中,一块内存就是一个对象。
在c++中,如果你不处理POD类型(类似于C类型),你必须在内存位置上调用构造函数来实际拥有一个对象。非pod类型在c++中非常常见,因为许多c++特性使对象自动变为非pod类型。
New分配内存并在该内存位置上创建一个对象。对于非pod类型,这意味着调用构造函数。
如果你这样做:
non_pod_type* p = (non_pod_type*) malloc(sizeof *p);
您获得的指针不能被解引用,因为它不指向对象。在使用它之前,您需要调用它的构造函数(这是使用placement new完成的)。
另一方面,如果你有:
non_pod_type* p = new non_pod_type();
你得到一个总是有效的指针,因为new创建了一个对象。
即使是POD类型,两者之间也有显著差异:
pod_type* p = (pod_type*) malloc(sizeof *p);
std::cout << p->foo;
这段代码将打印一个未指定的值,因为由malloc创建的POD对象没有初始化。
使用new,可以指定要调用的构造函数,从而获得定义良好的值。
pod_type* p = new pod_type();
std::cout << p->foo; // prints 0
如果你真的想要它,你可以使用use new来获得未初始化的POD对象。有关更多信息,请参阅另一个答案。
另一个区别是失败时的行为。当它分配内存失败时,malloc返回一个空指针,而new则抛出异常。
前者要求您在使用它之前测试返回的每个指针,而后者将始终产生有效的指针。
基于这些原因,在c++代码中应该使用new,而不是malloc。但即便如此,你也不应该“公开”使用新的内容,因为它会占用你以后需要发布的资源。当你使用new时,你应该立即将它的结果传递给一个资源管理类:
std::unique_ptr<T> p = std::unique_ptr<T>(new T()); // this won't leak
其他回答
除非被迫使用C,否则永远不要使用malloc。总是使用new。
如果你需要大量的数据,可以这样做:
char *pBuffer = new char[1024];
尽管这是不正确的,但要小心:
//This is incorrect - may delete only one element, may corrupt the heap, or worse...
delete pBuffer;
相反,你应该在删除数据数组时这样做:
//This deletes all items in the array
delete[] pBuffer;
new关键字是c++实现它的方式,它将确保你的类型的构造函数被调用。new关键字也更加类型安全,而malloc根本不是类型安全的。
我认为使用malloc有益的唯一方式是需要改变数据缓冲区的大小。new关键字没有类似realloc的方式。realloc函数可能能够更有效地扩展内存块的大小。
值得一提的是,你不能将new/free和malloc/delete混合使用。
注:本题部分答案无效。
int* p_scalar = new int(5); // Does not create 5 elements, but initializes to 5
int* p_array = new int[5]; // Creates 5 elements
只使用malloc和free来分配将由以c为中心的库和api管理的内存。对你控制的所有东西使用new和delete(以及[]变量)。
malloc()在C语言中用于动态分配内存 而在c++中,同样的工作由new()完成。 所以你不能混合两种语言的编码习惯。 如果你问calloc和malloc()之间的差异,那就好了
我以前玩过很少的计算机图形C/ c++应用程序。 过了这么久,有些东西消失了,我很想念它们。
关键是,malloc和new,或free和delete,可以同时工作, 特别是对于某些基本类型,这是最常见的。
例如,一个char数组可以用malloc或new来分配。 一个主要的区别是,使用new,你可以实例化一个固定的数组大小。
char* pWord = new char[5]; // allocation of char array of fixed size
在这种情况下,不能使用变量来表示数组的大小。 相反,malloc函数可以允许变量大小。
int size = 5;
char* pWord = (char*)malloc(size);
在这种情况下,可能需要一个转换强制转换操作符。 对于malloc返回的类型,它是指向void的指针,而不是char。 有时候编译器不知道如何转换这个类型。
分配内存块后,可以设置变量值。 对于一些较大的数组,memset函数确实会慢一些。 但是在赋值之前,所有的bit必须先设置为0。 因为数组的值可以有任意的内容。
假设,数组被分配给另一个较小的数组。 数组元素的一部分仍然可以有任意内容。 在这种情况下,建议调用memset函数。
memset((void*)pWord, 0, sizeof(pWord) / sizeof(char));
分配函数可用于所有C包。 这些是通用函数,必须适用于更多的C类型。 c++库是旧C库的扩展。 因此malloc函数返回一个泛型void*指针。 该结构没有定义new或delete操作符。 在这种情况下,可以使用malloc分配自定义变量。
new和delete关键字实际上是一些定义好的C操作符。 也许一个自定义联合或类可以定义这些操作符。 如果在类中没有定义new和delete,则它们可能不起作用。 但如果一个类是由另一个类派生的,这个类有这些操作符, new和delete关键字可以具有基本的类行为。
关于释放数组,free只能与malloc结合使用。 不能使用malloc分配变量,然后使用delete释放变量。
简单的删除操作符只引用数组的第一项。 因为pWord数组也可以写成:
pWord = &pWord[0]; // or *pWord = pWord[0];
当必须删除一个数组时,使用delete[]操作符:
delete[] pWord;
类型转换并不坏,只是不适用于所有的变量类型。 转换类型转换也是一个必须定义的运算符函数。 如果没有为某个类型定义此操作符,则它可能不起作用。 但并不是所有的错误都是由这个转换强制转换操作符引起的。
另外,在使用自由调用时,必须使用到空指针的类型转换。 这是因为free函数的实参是一个空指针。
free((void*)pWord);
可能会出现一些错误,因为数组的大小太小。 但这是另一个故事,并不是因为使用了演员阵容。
致以亲切的问候,艾德里安·布里纳斯
如果你有C代码,你想移植到c++,你可能会留下任何malloc()调用。对于任何新的c++代码,我建议使用new。