SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Modern C++入門

かつての当たり前が通用しない? Modern C++ではやらないこと

第1回 newもdeleteも呼ばないで!

  • X ポスト
  • このエントリーをはてなブックマークに追加

あの頃のC++と、もはややらないこと

 今回は、1990年ごろ当時は当たり前にやっていたけど、今はどうやらそうではないらしいということがらをいくつかピックアップし、紹介します。次回からは、Modern C++のことをいろいろ紹介していきますが、そのための地ならしみたいな感じでお付き合いください。

1. newもdeleteも呼ばないで!

  • new演算子もdelete演算子も使わない。
  • インスタンスの生成はmake_unique関数とmake_shared関数で。

 1990年ごろにC++を始めた人にとって、C言語にはなかったいろんな構文を使うのがうれしくもあり、誇らしくもありました。何しろ、Javaが1990年代中盤ごろに登場するまでは、C++が唯一の実用的なオブジェクト指向プログラミングが可能な言語プラットフォームでしたから。C言語でゴリゴリ書いていた、構造体を使うコードをクラスに置き換え、メモリ確保と初期化を同時に行えるなど、意識してC++の世界に浸ろうとしていたものです。

 リスト1を見てください。なんてことないC言語のコードです。構造体を定義し、その領域をヒープ上に確保、フィールドを初期化して出力し、使い終わったら解放するというコードです。C言語のコメントにダブルスラッシュが使えるようになったのはC99からなので、ここではあえて古いスタイルとしています。

[リスト1]構造体を使うC言語のコード(struct.c)
#include "stdio.h"
#include "stdlib.h"

/* 構造体を定義する */
struct MyStructure {
    int id;
    char name[16];
};

int main()
{
    /* 構造体のメモリを確保する */
    struct MyStructure *s = (struct MyStructure *)malloc(sizeof(struct MyStructure));
    /* 構造体のメンバを初期化する */
    s->id = 1;
    s->name[0] = 'A';
    /* 構造体のメンバを出力する */
    printf("%d: %c\n", s->id, s->name[0]);
    /* 構造体のメモリを解放する */
    free(s);
    return 0;
}

 C++の世界に移すにあたり、こんな構造体があったら、これをわざわざクラスにして、コンストラクタを作って初期化もクラス任せにしようということをするわけです。C++では、ダブルスラッシュによるコメントが使えました(リスト2)。

[リスト2]クラスを使うC++のコード(class.cpp)
#include <iostream>
using namespace std;

// クラスを定義する
class MyClass {
public:
    MyClass();		// デフォルトコンストラクタ

    int id;
    char name[16];
};

// デフォルトコンストラクタ
MyClass::MyClass() {
    // メンバを初期化する
    id = 0;
    name[0] = '\0';
}

int main()
{
    // クラスのインスタンスを生成する
    MyClass *c = new MyClass();
    // クラスのメンバを出力する
    c->id = 1;
    c->name[0] = 'A';
    cout << c->id << c->name[0] << "\n";
    // インスタンスを解放する
    delete c;
    return 0;
}

 ここではMyClassというクラスを定義しています。メンバは、先ほどの構造体と同じです。簡略化のために、MyClassクラスの全てのメンバはpublicであることをお許しください。publicにしたことで、全てのメンバはどこからでもアクセス可能、すなわち可視となります。C++のクラスでは、publicのようなアクセス制御子を記述しないと、デフォルトで全てのメンバはprivateすなわち不可視となります。

 メンバには、ほかにデフォルトコンストラクタがあります。これは、インスタンスの生成時にデフォルトで呼び出されるメソッドです。デフォルトコンストラクタには引数どころか戻り値もありません。なお、引数を与えて初期化の方法をカスタマイズできる、コンストラクタのオーバーロードを定義することができます。

 さて、クラスのインスタンスを動的に作成するときには、このようにnew演算子を使ってコンストラクタを呼び出し、使い終わったらdelete演算子でインスタンスを解放する、これがC++の流儀であり、長い間それだけだと思い込んでいました。何しろ、後発のJavaでもnew演算子を使ってインスタンスを生成するということが、Java 19になっても行われているのですから(Javaの場合は、インスタンスのお片付けは自動になっています)。

 このnew演算子とdelete演算子の組み合わせは、形が変わっただけでC言語におけるmalloc関数とfree関数の対応そのままです。newしたのにdeleteしなければメモリリークの原因になりますし、newしてないのにdeleteしようとしたらダングリングポインタを産み出してしまいます。やはり、このようなことはよくないということで、Modern C++ではmake_unique関数というものを使って安全にメモリの確保と解放が行えるようになっているらしいのです。この関数については第3回あたりで紹介できるのではないかと思います。

次のページ
2. 生のポインタは使わないで!

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Modern C++入門連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 山内 直(WINGSプロジェクト ヤマウチ ナオ)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook <個人紹介> WINGSプロジェクト所属のテクニカルライター。出版社を経てフリーランスとして独立。ライター、エディター、デベロッパー、講師業に従事。屋号は「たまデジ。」。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/16769 2022/12/01 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング