指针vs参考和清理它们

时间:2015-03-31 21:30:54

标签: c++ delete-operator

考虑以下代码:

#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方法在某些情况下可能会返回NULL(分配失败并被处理,参数无效等)。
  2. FOO是POD,但不是聚合
  3. 我想要的是:尽可能少删除调用(和内存泄漏)。

    我的观察:

    1. 我可以使用FOO :: CreatePtr,然后检查NULL并始终delete
    2. 我可以使用FOO :: CreateRef,但是我无法检查是否为空,我仍然需要delete
      1. FOO::CreateRefCreatePtr时,我可以让NULL返回一个特殊实例。这将有助于NULL检查,但仍然没有删除。
    3. 我可以使用本地变体,但我认为我的内存泄漏(CreatePtr(5)永远不会被删除,只会复制到local
      1. 这是非常无效的,因为有不必要的分配和副本
      2. 我无法使用大括号初始化,因为FOO不是聚合
    4. 有什么方法可以声明FOO类型的局部变量并在声明中初始化它,以便在函数退出时自动删除它?

2 个答案:

答案 0 :(得分:2)

如果无法创建对象,则抛出异常。无论如何它都更有用,因为它提供了更多的上下文,为什么无法创建对象并允许程序解决问题。此外,您还可以避免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;
}

答案 1 :(得分:0)

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

由于FOO应该是POD并且取决于其大小(取决于SOME_OTHER_BASE的大小),您可以通过create method中的值返回它:

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;
}