我看到在c++中有多种方法来分配和释放数据,我明白,当你调用malloc时你应该叫自由,当你使用新的操作符应与删除和对它是错误的把两个调用free()(例如,创建新的操作符),但是我不清楚我应该使用malloc / free,当我在现实世界中应该使用新的/删除程序。

如果你是c++专家,请告诉我你在这方面遵循的任何经验法则或惯例。


当前回答

从较低的角度来看,new将在提供内存之前初始化所有内存,而malloc将保留内存的原始内容。

其他回答

在c++中总是使用new。如果你需要一个无类型的内存块,你可以直接使用operator new:

void *p = operator new(size);
   ...
operator delete(p);

如果你有C代码,你想移植到c++,你可能会留下任何malloc()调用。对于任何新的c++代码,我建议使用new。

只有当对象的生命周期与创建它的作用域不同时才需要动态分配(这也适用于使作用域变小或变大),并且您有特定的原因按值存储它不起作用。

例如:

 std::vector<int> *createVector(); // Bad
 std::vector<int> createVector();  // Good

 auto v = new std::vector<int>(); // Bad
 auto result = calculate(/*optional output = */ v);
 auto v = std::vector<int>(); // Good
 auto result = calculate(/*optional output = */ &v);

从c++ 11开始,我们有std::unique_ptr来处理已分配的内存,它包含已分配内存的所有权。Std::shared_ptr是为必须共享所有权而创建的。(你需要的比你在一个好的程序中期望的要少)

创建一个实例变得非常简单:

auto instance = std::make_unique<Class>(/*args*/); // C++14
auto instance = std::unique_ptr<Class>(new Class(/*args*/)); // C++11
auto instance = std::make_unique<Class[]>(42); // C++14
auto instance = std::unique_ptr<Class[]>(new Class[](42)); // C++11

c++ 17还增加了std::optional,这可以防止你需要内存分配

auto optInstance = std::optional<Class>{};
if (condition)
    optInstance = Class{};

一旦'instance'超出作用域,内存就会被清理。转让所有权也很容易:

 auto vector = std::vector<std::unique_ptr<Interface>>{};
 auto instance = std::make_unique<Class>();
 vector.push_back(std::move(instance)); // std::move -> transfer (most of the time)

那你什么时候还需要新的?从c++ 11开始几乎没有。大多数情况下你使用std::make_unique,直到你遇到一个通过原始指针转移所有权的API。

 auto instance = std::make_unique<Class>();
 legacyFunction(instance.release()); // Ownership being transferred

 auto instance = std::unique_ptr<Class>{legacyFunction()}; // Ownership being captured in unique_ptr

在c++ 98/03中,您必须进行手动内存管理。如果您是这种情况,请尝试升级到标准的最新版本。如果你被卡住了:

 auto instance = new Class(); // Allocate memory
 delete instance;             // Deallocate
 auto instances = new Class[42](); // Allocate memory
 delete[] instances;               // Deallocate

确保正确跟踪所有权,以免出现内存泄漏!Move语义也不能工作。

那么,在c++中什么时候需要malloc呢?唯一有效的原因是分配内存并在以后通过放置new初始化它。

 auto instanceBlob = std::malloc(sizeof(Class)); // Allocate memory
 auto instance = new(instanceBlob)Class{}; // Initialize via constructor
 instance.~Class(); // Destroy via destructor
 std::free(instanceBlob); // Deallocate the memory

尽管如此,上面的操作是有效的,这也可以通过new操作符来完成。vector就是一个很好的例子。

最后,我们仍然有一个房间里的大象:C。如果你必须使用一个在c++代码中分配内存并在C代码中释放内存的C库(或者相反),你就被迫使用malloc/free。

如果你是在这种情况下,忘记虚函数、成员函数、类……只有包含pod的结构才被允许。

规则的一些例外情况:

您正在编写一个具有高级数据结构的标准库,其中malloc是合适的 你必须分配大量的内存(在10GB文件的内存副本中?) 您拥有阻止您使用某些构造的工具 您需要存储不完整的类型

在下面的场景中,我们不能使用new,因为它调用构造函数。

class  B  {
private:
    B *ptr;
    int x;
public:
    B(int n)  {
        cout<<"B: ctr"<<endl;
        //ptr = new B;  //keep calling ctr, result is segmentation fault
        ptr = (B *)malloc(sizeof(B));
        x = n;
        ptr->x = n + 10;
    }
    ~B()  {
        //delete ptr;
        free(ptr);
        cout<<"B: dtr"<<endl;
    }
};

New将初始化结构的默认值,并正确地将结构中的引用链接到结构本身。

E.g.

struct test_s {
    int some_strange_name = 1;
    int &easy = some_strange_name;
}

因此,new struct test_s将返回一个带有工作引用的初始化结构,而malloc'ed版本没有默认值,实习引用也没有初始化。