0

私がずっと前に見つけた記事 (ATM が見つかりません) があり、C++ の new キーワードが悪い理由を述べています。すべての理由を思い出すことはできませんが、最も覚えている 2 つは、new と delete、new[] と delete[] を一致させる必要があることと、malloc のように new と #define を使用できないことです。

私は言語を設計しているので、C++ 言語をどのように変更して、新しい言語をより親しみやすくするかを尋ねたいと思います。新しい記事や記事の問題を気軽に述べてください。記事のリンクが見つかればいいのですが、それは長くて、有名な学校 (IIRC) の教授によって書かれたことを覚えています。

4

8 に答える 8

6

キーワードを別のものに置き換える理由がわかりませnewん (C++ 委員会は私に同意しているようです)。それは明確で、あるべきものを作ります。operator newクラスでオーバーライドできます。定義を使用する必要はありません。

排除new[]/delete[]問題に使用できますstd::vector

スマート ポインターを使用したい場合は使用できますが、スマート ポインターをいつ使用するかを制御したいと考えています。そのため、C++ での動作が好きです。つまり、低レベルの詳細を制御できる高レベルの動作です。

于 2009-08-13T07:08:37.983 に答える
3

問題の一致 new、delete、new[]、delete[]

大したことではありません。
これが通常のユーザーに実際に影響を与えないように、クラス内でメモリ割り当てをラップする必要があります。1 つのオブジェクトをスマート ポインターでラップできます。配列は std::Vector<> で表すことができますが、

malloc で使用できるように、new で #define を使用することはできません。

このように malloc をいじる理由は、アプリと標準のメモリ管理レイヤーの間に独自のメモリ管理レイヤーを導入するためです。これは、C では独自のバージョンの malloc を作成することが許可されていなかったためです。C++ では、独自のバージョンの new を作成することは完全に合法であるため、このトリックは不要です。

于 2009-08-13T07:24:04.753 に答える
2

私はそれnewにC#のセマンティクスを与えます(多かれ少なかれ):

  1. オブジェクトにメモリを割り当てます。
  2. メンバー変数をデフォルト値に設定することにより、メモリを初期化します (通常、値の場合は 0、null参照の場合)。
  3. オブジェクトの動的バインディング メカニズムを初期化します (C++ の vtables、マネージド VM の型定義テーブル)。
  4. コンストラクターを呼び出します。その時点で、仮想呼び出しは期待どおりに機能します。
  5. ガベージ コレクションのない言語 (この時点での新しい言語の eww ) の場合smart_ptr、呼び出しから a または類似のものを返します。

また、すべてのオブジェクトを値型または参照型にすることで、明示的に保持する必要がなくなりsmart_ptrます。参照型のヒープ割り当てのみを許可newし、デストラクタを適切に呼び出すための情報が含まれていることを確認してください。値型の場合new、スタックからメモリ上のコンストラクターを呼び出します。

于 2009-08-13T07:07:47.813 に答える
1

STL コンテナー クラスとさまざまな boost:smart_ptrs を使用することで、C++ コードで明示的に new または delete を呼び出す必要はほとんどありません。

new を呼び出す必要があるいくつかの場所 (スマート ポインターを初期化する場合など) では、名前付きコンストラクターのイディオムを使用して、クラス型ポインターをaなどでboost:shared_ptrラップして返します。

しかし、C++ と STL は、ほとんどのオブジェクトを値オブジェクトとして扱えるようにするために非常に苦労しています。そのため、ポインターではなくオブジェクトを構築して、それらをそのまま使用することができます。

これらすべてを考慮すると、new 演算子を置き換える必要はほとんどありません。そうすると、ガベージ コレクターが必要になるか、C++ がプログラマーに提供する細かい低レベル制御が減少するかによって、多くの問題が発生します。

于 2009-08-13T07:20:43.027 に答える
1

new を何かと一致させる必要がないように、Garbage Collection を使用します。

于 2009-08-13T07:05:48.457 に答える
0

C ++に個別のnew演算子(またはC malloc)がある理由は、主に、オブジェクトを作成する関数のスコープを超える存続期間を持つオブジェクトを作成できるようにするためです。

末尾呼び出しの削除と継続がある場合は、気にしないでください-オブジェクトはすべてスタック上に作成され、無制限の範囲を持つことができます-スコープ外に出て破壊されるオブジェクトに対応する継続を呼び出すまで、オブジェクトは存在できます。次に、スタックをガベージコレクションするか、圧縮して、不要になったオブジェクトでいっぱいにならないようにする必要がある場合があります(ChickenSchemeとTinyOS2は、実行時または動的メモリなしで動的メモリの効果を与えるための2つの異なる例です。コンパイル時間;ChickenスキームはRAIIを許可せず、TinyOSは真の動的割り当てを許可しません)。ただし、大量のコードの場合、このようなスキームは、順序を変更する機能を備えたRAIIと大きく異なることはありません。オブジェクトは破棄されます。

于 2009-08-13T09:01:50.470 に答える
0

新しい言語がガベージ コレクションされている場合は、new キーワードを避けることができます。それが Python が行ったことです (そして Lisp はほぼ 50 年前に行いました!)。同様の質問に対する Peter Norvig の回答も参照してください。(「ニュース」は良いニュースではありませんか?)

于 2009-08-13T07:28:23.090 に答える
0

コンストラクタをファクトリに置き換えたい場合があります。これはよく知られたリファクタリングです。コンストラクターを Factory Method に置き換えます。ということは、この記事の意味はこれだったのでしょうか。

ちなみに、 new への直接の呼び出しがFactory Methodに置き換えられていることがよくあります。

Unityなどの DI フレームワークは、この概念を別のレベルに引き上げます。次の C# コードでわかるように、IMyClass インターフェイスを作成するために適用される "new" はありません。

IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType<IMyClass, SomeClass>();
IMyClass thing = myContainer.Resolve<IMyClass>();
于 2009-08-13T07:29:22.323 に答える