簡體   English   中英

指針與引用並清除所有內容

[英]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方法在某些情況下可能會返回NULL(分配失敗並被處理,參數無效等)。
  2. FOO是POD,但不是匯總

我想要的是:盡可能少的刪除調用(和內存泄漏)。

我的觀察:

  1. 我可以使用FOO :: CreatePtr,檢查NULL然后始終delete
  2. 我可以使用FOO :: CreateRef,但是我不能真正檢查null還是必須delete
    1. CreatePtrNULL時,我可以使FOO::CreateRef返回一個特殊實例。 這將有助於進行NULL檢查,但仍然無法刪除。
  3. 我可以使用local變體,但是我想我那里有內存泄漏( CreatePtr(5)永遠不會被刪除,只會復制到local
    1. 這是非常無效的,因為有不必要的分配和副本
    2. 我不能使用大括號初始化,因為FOO不是聚合

有什么辦法可以聲明FOO類型的局部變量並在聲明中對其進行初始化,以便在函數退出時將其自動刪除?

如果無法創建對象,則引發異常。 無論如何,它更有用,因為它提供了更多無法創建對象的上下文,並允許程序解決此問題。 另外,由於不使用new因此可以避免delete的問題。 如果要多態使用該類型,則需要使用諸如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;
}

不知道是否應該針對您的情況使用指針。
此外,您不會刪除創建到local變量的指針。

由於FOO應該是一個POD,並取決於其大小(取決於SOME_OTHER_BASE的大小),因此可以從create方法中按值返回它:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM