2016-06-13 10 views
2

コンストラクタがいくつかの例外を生成するときに役立つスマートポインタを読みました。スマートポインタとコンストラクタの例外

問題は、コンストラクタが例外生成前にいくつかのリソースを取得したが、デストラクタが呼び出されない(リソースが永続的にビジー状態になる)という問題です。

しかし、私は正しくそれをundestandすることはできません。 マイコード:

#include <memory> 
#include <iostream> 

class resOwner { 
    public: 
    resOwner() { 
     std::cout << "Map some huge resources\n"; 
     throw "hi"; 
    } 

    ~resOwner() { 
     std::cout << "Free some huge resources\n"; 
    } 
}; 

class normal : resOwner { 
}; 

int main(){ 
    try { 
     std::shared_ptr<resOwner> k (new resOwner()); 
    } catch (...) {} 
} 

出力がMap some huge resourcesです。 どのようにスマートポインタでこのリソースリークを解決するには?

+1

心配しないでください - http://stackoverflow.com/questions/1674980/who-deletes-the-を参照してください - C-TORがスローした場合、メモリが解放される - スマートポインタからの協力なし – PiotrNycz

+0

リソース 'resOwner'が所有するリソースは、何らかのスマートポインタ' unique_ptr'や 'shared_ptr'などでなければなりません。そうしないと、リソースリークが発生しますデストラクタでクリーンアップを計画していたものは呼び出されません。 – Arunmu

+1

単一のコンストラクタがコンプリート(コンストラクタデリゲーション)まで実行され、デリゲートコンストラクタがスローした場合、オブジェクトのデストラクタが呼び出されることは重要です。 – Blazo

答えて

4

どのようにスマートポインタでこのリソースリークを解決するには?

リソースをRAIIコンテナにラップし、コンテナをresOwnerのメンバとして格納します。スマートポインタは必ずしも必要ではありません。 std::unique_ptr:その巨大なリソースが動的に割り当てられたオブジェクトがある場合は、標準ライブラリはすでにそれらのための容器を持っているので

struct resource { 
    resource() { 
     std::cout << "Map some huge resources\n"; 
    } 
    ~resource() { 
     std::cout << "Free some huge resources\n"; 
    } 
}; 

struct resOwner { 
    resource res; 
    resOwner() { 
     throw "hi"; 
    } 
}; 

、あなたは、別のresourceクラスを実装する必要はありません。動的に割り当てられた配列の場合は、std::vectorを使用できます。

方法:コンストラクタ本体またはサブオブジェクトコンストラクタのいずれかがスローすると、すでに構築されているすべてのサブオブジェクト(メンバーおよびベースオブジェクト)が破棄されます。これにより、~resourceが呼び出されることが保証されます。

3

スマートポインタをリソースと併用すると、リソースリークを防ぐのに役立ちます。以下のような:オブジェクトが実際に作成される前に、

class resource { 
public: 
    resource() { 
     std::cout << "resource allocated\n"; 
    } 
    ~resource() { 
     std::cout << "resource deallocated\n"; 
    } 
}; 

class resOwner { 
    std::shared_ptr<resource> res; 
public: 
    resOwner() : res(new resource) { 
     std::cout << "Map some huge resources\n"; 
     throw "hi"; 
     // res will be destroyed even though exception happened 
    } 
    ~resOwner() { 
     // nothing need to do here 
    } 
}; 

LIVE

1

例外がスローされます。オブジェクトが作成されないので、そのデストラクタは呼び出されません。

一方、コンストラクタ内で例外がスローされた場合、コンストラクタが実行を完了したすべてのサブオブジェクトに対して、デストラクタが呼び出されます。比較のためにこれを試してみてください:

class Resource 
{ 
public: 
    Resource() 
    { 
     std::cout << "constructing resource" << std::endl; 
    } 
    ~Resource() 
    { 
     std::cout << "destroying resource" << std::endl; 
    } 
}; 

class Owner 
{ 
    ::std::unique_ptr <Resource> theResource; 
public: 
    Owner() 
      : theResource(new Resource()) 
    { 
     std::cout << "Map some huge resources\n"; 
     throw "hi"; 
    } 

    ~Owner() 
    { 
     std::cout << "Free some huge resources\n"; 
    } 
}; 
関連する問題