C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++のnewキーワードとoperator newの違いをわかりやすく解説

C++でオブジェクトを生成する際には、メモリ上にブロックを確保し、さらにコンストラクタを呼び出してそのメモリブロックを初期化するという2段階の処理が必要になります。通常、私たちが new キーワードを使ってオブジェクトを作成すると、この2つの処理が連続して実行されます。一方、operator new はメモリ領域の確保だけを行う関数です。本記事では、この2者の違いを具体例とともに詳しく解説します。

newキーワードとは

new 演算子は、ヒープ領域へのメモリ割り当てを要求するための特殊な演算子です。十分なメモリが利用可能な場合にのみ、確保されたメモリへのポインタ変数が返されます。通常の new キーワードを使ってオブジェクトを生成すると、次の2つの処理が連続して実行されます。

  • オブジェクト用のメモリブロックをヒープ領域に確保する
  • コンストラクタを呼び出して、そのメモリブロックを初期化する

サンプルコード

#include <iostream>
using namespace std;

class Box {
   public:
   Box() {
      cout << "Constructor called!" << endl;
   }
};

int main() {
   Box* myBox = new Box;
}

出力結果

Constructor called!

この例では、new Box; の実行時にメモリ確保とコンストラクタ呼び出しの両方が行われているため、「Constructor called!」が出力されます。

operator newとは

operator new は関数であり、new 演算子をオーバーロードするために使用されます。この関数を使うことで、生の(初期化されていない)メモリブロックを確保できます。概念的には、C言語の malloc()calloc() 関数に似ています。

重要なポイントとして、operator new はコンストラクタを呼び出さないため、確保されたメモリは初期化されません。ただし、このオーバーロードされた関数からポインタが返された後、コンパイラが自動的にコンストラクタを呼び出します。

サンプルコード

#include <iostream>
#include <cstdlib>
using namespace std;

class Box {
   public:
   Box() {
      cout << "Constructor called!" << endl;
   }
   void *operator new(size_t size) {
      cout << "Call Operator New" << endl;
      void *p = malloc(size);
      return p;
   }
};

int main() {
   Box* myBox = new Box;
}

出力結果

Call Operator New
Constructor called!

この例では、まずオーバーロードされた operator new が呼び出されてメモリが確保され、その後コンストラクタが呼び出されていることが出力から確認できます。

まとめ:両者の違い

項目newキーワードoperator new
役割メモリ確保+コンストラクタ呼び出しメモリ確保のみ
種類演算子関数(オーバーロード可能)
類似機能malloc() / calloc()
初期化コンストラクタにより初期化される単独では初期化されない

つまり、new キーワードは「メモリ確保」と「初期化」をまとめて行う高レベルな仕組みであり、operator new はその中の「メモリ確保」部分だけを担う低レベルな関数だと理解するとよいでしょう。カスタムのアロケーション戦略を実装したい場合などに、operator new をオーバーロードすることで柔軟なメモリ管理が可能になります。

  1. C++におけるドット演算子(.)とアロー演算子(->)の違いを徹底解説

    C++では、ドット演算子(.)とアロー演算子(->)はどちらもクラスのメンバーにアクセスするために使用されますが、それぞれ使用される場面が異なります。C++において、class、struct、unionとして宣言された型はすべて「クラスタイプ」とみなされるため、以下の説明はこれら3つすべてに当てはまります。基本的な使い分けa.b は、b がオブジェクト a(またはオブジェクトへの参照[1])のメンバーである場合にのみ使用できます。つまり、a.b の形式では、a は常にクラスの実際のオブジェクト(またはその参照)でなければなりません。a->b は、本質的に (*a).b の省略記法で

  2. 「!==」と「==!」の違いを解説!PHPの比較演算子

    PHPには一見よく似ていますが、動作がまったく異なる演算子が存在します。その代表格が「!==」と「==!」です。この記事では、それぞれの演算子の意味と違いを、サンプルコード付きでわかりやすく解説します。 「!==」比較演算子とは 「!==」は「型も含めて等しくない」ことを判定する比較演算子です。値の比較時にデータ型の自動変換(型ジャグリング)を行わず、厳密な型チェックを実施します。そのため、たとえば 1 !== 1 は数値の1と文字列の1というように型が異なるため、true を返します。 「==!」比較演算子とは 実は「==!」という単一の演算子は存在しません。「==!」は「==」と「!」