「C++ は難しいから」と言う定説

雑記.

C++ は難しいから Java から始めた方が・・・

ここ最近(と言うか以前からずっとですが),上記のようなアドバイスを見かける機会が多かったせいか「C++ の何を指して(Java と比べて)難しいと言っているのだろう?」と言う事を単純に疑問に思うようになりました.Java 自体はほとんど使ったことないのですが*1,感想としては「どちらも大して変わらない」と言うものだったので余計に気になっています.

以下,現状で私が「これが要因かなぁ」と思っている事を列挙してみます.

C++ には XXX と言うクラス/関数がない

可能性として一番高いのはこれかなぁと思っています.C++ の標準ライブラリは必要最低限のものしか(必要最低限のものさえも?)用意されていないので,他の言語と比べてライブラリの貧弱さは目立ちます.Boost を含めればかなりマシになりますが,それでもキツいかなと言う印象を受けます(参考:プログラミング言語の力における限界生産力逓減の法則とライブラリと - プログラミング言語を作る日記).

ポインタが分らない

ポインタは何かと嫌われています.「ポインタが分らない」と言うフレーズは,プログラミングの習得に挫折した人の原因の一つとして半ばネタのようによく利用されています(されていた?).

この問題は,C++ では,「参照型」の存在を広く認知させる事と std::string, std::vector などの STL を使用を推奨していくことで和らげることができるでしょうか.

ガベージコレクションがない

これはよく言われます.C++ に限らず,「XXX の言語はガベージコレクションがないのでやってられません」みたいな言葉はしばしば耳にします.後,メモリリークが〜と言うのもここに該当するでしょうか.

これは,個人的には何とも言えません.自分がコーディングしている限りでは(大抵の場合は STL に任せるため),自分で動的に領域を確保して管理する機会に遭遇することがそもそもあまりないので STL と(場合によっては)スマートポインタの併用で問題を感じたことはないのですが(参考:はてなブックマーク - c++ templateとか - nak2kのメモ帳),人によっては大きな問題なのかもしれません.

template が難しい

※この項目はブクマの反響を受けて追加.

未だに「template は使用禁止!」のような話を聞く位ですから,template はかなりとっつきにくいのだろうと思います.これに関しては,当初は「Java も generic 導入したんだからもう同じじゃね?」と思っていたのですが,Java の generic は 5.0 以降に新しく導入された機能なので「generic ガン無視(Java 1.4 以前)でも書ける Java」と「STL 等ほとんどのものにおいて template が密接に絡んでいる C++」の差があるのかなぁと思いました.

C++ の template と Java の generic (generics?) はだいぶ違う,と言う指摘を頂いたので上記の記述は保留.Java についてもう少し調べてからまた考えます.

Effective なんちゃらを10冊位読まなければならない

半分ネタ.でも割とマジで語られているお話(参考:Effective なんとかを読めば良いというものではない - 神様なんて信じない僕らのために).

名前空間の存在

※これ以降の項目は,C++は難しい で挙げられていた項目です.

後輩に仕事で C++ を触らせたときにの最初の感想が,「std:: みたいなのが気持ち悪い」でした.名前空間のような概念のある言語を知っている場合は問題ないのですが,そうでない場合“xxx::yyy”と言う記法はあまり直観的でないのかもしれません.

typename の存在

C++ では,後続する記述が型を表していることを明示するための typename と言うキーワードが存在します(参考:テンプレートあれこれ (4) -- typename の役割 - C++ labyrinth).確かに,私自身も「typename は必要かどうか」の判断はかなり曖昧で,ほとんどの場合コンパイラ便りになってしまいます(最近は,typename の有無でコンパイルエラーを出すことはなくなりましたが).

const の使い分け

const には,関数/メソッドの引数の頭に付加して「渡された引数の内容を変更しない(できない)」と言う事を明示する使い方以外に,下記のような使い方があります (参考:const の取り扱い - Life like a clown).

class foo {
public:
    int bar() const { return bar_; }

private:
    int bar_;
};

メソッドの最後に const を付けた場合,そのメソッドは,const 付で渡されたインスタンスからも呼び出せる事を表します.逆に,const の付いていないメソッドは,const 付で渡されたインスタンスからは呼び出すことができません.

これは,私も知るまでは何の意味があるのか分らなかった項目の一つです.

後置インクリメントの宣言方法

C++ は,(+ や - などの)演算子プログラマが挙動を定義することができます.この際,インクリメント/デクリメントの存在が問題となります.インクリメント/デクリメントには,++i のような前置インクリメントと i++ のような後置インクリメントが存在しますが,C++ のメソッド定義での表記方法ではこれらを書き分ける方法がありません.

そのため,C++ では,以下のように書くと後置インクリメント/デクリメント(i++ とか)を表すと言う決まりがあります(前置インクリメント/デクリメントは,object& operator++();).

object operator++(int);

これも知らない場合は,混乱する箇所ですね.

思いついたら,また追記していこうと思います.まぁ,個人的には C++ でも Java でもあんま変わらないと思っているので,Java を選んでも問題ないような気はします.

私は,Java のメソッドの命名規則(最初の1文字だけ小文字)が嫌いなので使いません:p

*1:大学の講義で Java 1.4 以前を触ったのと,知り合いにヘルプを頼まれて少し現 Java(5.0? 6.0?)を触った程度