指针 vs 引用并清理它

Pointers vs references and cleaning it all up

考虑这段代码:

#include <iostream>
using namespace std;

struct SOME_OTHER_BASE {
    // members
};

struct FOO : SOME_OTHER_BASE {
    int value;
    static FOO *CreatePtr(int param) 
    { 
        FOO *res = new FOO(); 
        res->value = param; 
        return res;
    }
    static FOO &CreateRef(int param)
    {
        return *CreatePtr(param);
    }
};

int main() {
    FOO *ptr = FOO::CreatePtr(2);
    FOO &ref = FOO::CreateRef(4);
    FOO local = FOO::CreateRef(5);

    cout << "ptr: " << ptr->value << endl;
    cout << "ref: " << ref.value << endl;
    cout << "local: " << local.value << endl;

    delete ptr;
    delete &ref;
    return 0;

要求:

  1. FOO::CreatePtr 方法在某些情况下可能 return NULL(分配失败并被处理,参数无效等)
  2. FOO 是 POD,但不是聚合

我想要的:尽可能少的删除调用(和内存泄漏)。

我的观察:

  1. 我可以使用 FOO::CreatePtr,检查 NULL,然后总是 delete
  2. 我可以使用 FOO::CreateRef,但我无法真正检查 null,我仍然必须 delete
    1. CreatePtrNULL 时,我可以使 FOO::CreateRef return 成为一个特殊实例。这将有助于 NULL 检查,但仍然无助于删除。
  3. 我可以使用本地变体,但我认为我那里有内存泄漏(CreatePtr(5) 永远不会被删除,只会被复制到 local 中)
    1. 这是非常低效的,因为有一个不必要的分配和一个副本
    2. 我不能使用大括号初始化,因为 FOO 不是聚合

有什么方法可以声明 FOO 类型的局部变量并在声明中对其进行初始化,以便在函数退出时自动将其删除?

不确定是否应该为您的情况使用指针。
此外,您并没有删除为 local 变量创建的指针。

因为 FOO 应该是一个 POD 并且取决于它的大小(这取决于 SOME_OTHER_BASE 的大小),你可以 return 它通过你的创建方法的值:

struct FOO : SOME_OTHER_BASE {
    int value;
    static FOO Create(int param) {
        FOO foo;
        foo.value = param;
        return foo;
    }
};

int main() {
    FOO local = FOO::Create(2);
    FOO &ref = local;
    FOO *ptr = new FOO(FOO::Create(6));
    // can check if ptr is NULL if you want

    cout << "local: " << local.value << endl;
    cout << "ref: " << ref.value << endl;
    cout << "ptr: " << ptr->value << endl;

    delete ptr;
    return 0;
}

如果无法创建您的对象,则抛出异常。无论如何,它更有用,因为它提供了更多无法创建对象的上下文,并允许程序修复问题。您还避免了 delete 的问题,因为您不使用 new。如果要以多态方式使用该类型,则需要使用 std::unique_ptrstd::shared_ptr.

等智能指针
#include <iostream>
#include <stdexcept>
using namespace std;

struct SOME_OTHER_BASE {
    // members
};

struct CreationFailure : std::runtime_error
{
    CreationFailure(const std::string& s) :
        std::runtime_error(s)
    {

    }
};

struct FOO : SOME_OTHER_BASE {
    int value;

    FOO(int value) : 
        SOME_OTHER_BASE(), // pass the constructor arguments
        value(value)
    {
        // additional actions
        if(/* creation failed */)
            throw CreationFailure("out of memory");
    }
};

int main() {
    FOO local(2);

    cout << local.value << endl;
    return 0;
}

如果不能添加构造函数,同样的逻辑可以移到工厂函数中:

FOO createFoo(int v)
{
    FOO f;
    f.value = v;
    if(/* creation failed */)
        throw CreationFailure("out of memory");
    return f;
}