6

しばし疑問に思ったのですが、

newキーワードを使用して、関数への引数として同じポインターを渡すと同時に、オブジェクトのインスタンスへのポインターを作成できることを知っています。以下の例に示すように、Animation::newFrame関数で以下のようにします。

ただし、原則として、deleteを使用して作成したものを呼び出すのは自分の責任であることも認識していますnew

したがって、Frame のコンストラクターを次のように呼び出すと、次のようになります。

Frame* myFrame
    = new Frame(new point(0,0), new point(100,100), new point(50,20));

new上記の関数呼び出しで作成した 3 つのポイントのメモリを最終的に解放する責任はどこにありますか?

結局のところ、上記の 3 つの新しいポイントには、私が呼び出す名前が正確にはありませんdelete

私は常に、それらが呼び出された関数のスコープに属していると想定してきましたが、それらは単に関数のスコープから外れます。しかし、そうではないのではないかと最近思うようになりました。

ここで十分に明確になったことを願っています。

前もって感謝します、

struct Frame
    {
    public:
        point f_loc;
        point f_dim;
        point f_anchor;

    //the main constructor:: Creates a frame with some specified values
        Frame(point* loc, point* dim, point* anchor)
        {
            f_loc = loc;
            f_dim = dim;
            f_anchor = anchor;
        }

    };

struct Animation
    {
    public:
        vector<Frame*> frameList;

    //currFrame will always be >0 so we subtract 1
        void Animation::newFrame(int &currFrame)
        {
            vector<Frame*>::iterator it;//create a new iterator
            it = frameList.begin()+((int)currFrame);//that new iterator is 

                    //add in a default frame after the current frame
            frameList.insert(
                        it,
                        new Frame(
                            new point(0,0),
                            new point(100,100),
                            new point(50,20)));

            currFrame++;//we are now working on the new Frame

        }

        //The default constructor for animation. 
        //Will create a new instance with a single empty frame
        Animation(int &currFrame)
        {
                frameList.push_back(new Frame(
                    new point(0,0),
                    new point(0,0),
                    new point(0,0)));

                currFrame = 1;
        }
    };

編集:この質問は純粋に理論的なものであることを忘れていました。スマート ポインターなどの生のポインターに代わるはるかに優れた代替手段があることを認識しています。通常のポインターとその管理方法についての理解を深めたいという単純なお願いです。

また、上記の例は、実際には C++/cli と c++ が混在する (マネージド クラスとアンマネージド クラス) である私のプロジェクトから取得したものです。そのため、コンストラクターは値のみを受け入れpoint*、値を渡さないのです ( point)。はアンマネージ構造であるためpoint、マネージ コード内で使用する場合は、プログラマーである私自身が管理する必要があります。:)

4

7 に答える 7

11

リソース所有権のセマンティクスを明確にし、多くの場合強制することは、プログラマーの責任です。リソースの所有権が実際の設計上の考慮事項に与えられていない環境で、ここにいるように生のポインターを処理する場合は特に、これはトリッキーなビジネスになる可能性があります。後者は、新人プログラマーが作成したおもちゃのプログラムだけでなく、何十年もの経験を積んでいる人が作成した製品システムでもよく見られます。

上記の実際のケースでは、渡された 3 つのポインターFrameをオブジェクト自体が処理する必要があり、それ自体を構築したものはそれを処理する必要があります。deleteFramedelete

リソースの所有権は非常に地雷原であるため、プログラマーはかなり前に所有権のセマンティクスを明確にするための多くの手法を発明し、不注意なプログラマーによるバグやリークの導入をはるかに困難にしました。最近の C++ では、リソースの所有権が非常に危険な地雷原であるため、可能な限り生のポインターと、実際には動的割り当てを完全に回避することがベスト プラクティスと見なされています。

C++ では、これらの目標を達成するために使用される主なイディオムは RAII であり、使用される主なツールはauto_ptr(C++03)、unique_ptrshared_ptrおよびそれらの同類です。Boost はまた、いわゆる「スマート ポインター」を多数提供します。これらの多くは、C++11 に見られるものと類似していますが (実際、C++11 の新しいスマート ポインターは最初は Boost によって開発されました) intrusive_ptr、.

于 2013-09-25T13:15:58.873 に答える
2

まず、コンパイルできるようにコードを修正する必要があります。たとえば、 apoint*を aに割り当てることはおそらくできません ( の実装によって異なります)。pointpoint

あなたがそれをしたら、あなたの質問への答えは、その中のAnimationすべてを解放する必要があり、渡されたs を解放する必要があるということです。生のポインターは削除されません。frameListFramepoint*

より良い答えは(あなたが求めたものとはまったく異なりますが)、メモリを使用shared_ptrまたはunique_ptr管理する必要があるということです-これらは、ポイントされたオブジェクトを削除します。それは間違いなく私がframeListすることです-それをstd::vector<std::shared_ptr<Frame>>.

この場合、おそらくpoints にポインタを使用する正当な理由はありません (それらは単なる座標であり、コピーするのは非常に安価だと思います) - 値または const 参照で渡すだけです。そうすれば、ヒープ割り当てが関係なく、はるかに簡単になります。

于 2013-09-25T13:15:49.677 に答える
1

それは規約に大きく依存します。これは GUI の一部のように見えます。GUI の通常のdelete慣習では、ポインターを渡された後は、それを含むオブジェクトが責任を負います。したがって、デストラクタ 内のすべてのポインタAnimationが削除され、デストラクタに保持されているすべてのポインタが削除されます。(ただし、この規則は GUI に非常に特有のものであり、他のほとんどのコンテキストでは他の規則が使用されることに注意してください。)deleteframeListFrame

そうは言っても、Point最初から動的に割り当てられるような値はC++では非常に非典型的であり、それらへのポインターもありません。

于 2013-09-25T13:35:45.043 に答える
1

呼び出している関数が、完了時に渡されたポインターの所有権を取得することを明示的に述べていないdelete場合、それはあなた自身の責任deleteですnew

于 2013-09-25T13:16:45.050 に答える