パスワードを忘れた? アカウント作成
11961872 story
プログラミング

Linus TorvaldsのC++批判は正しかったのか 130

ストーリー by headless
主張 部門より
本家/.「Was Linus Torvalds Right About C++ Being So Wrong?」より

最も有名なC++への批判は、おそらく2007年のLinus Torvalds氏の発言だろう。「C++はひどい言語だ。」彼はこう書き始める。「これをさらにひどいものにしているのは、水準以下のプログラマーが数多く使用していることで、またさらに簡単に完全なゴミを作り出せるようになっている点だ。」と続く。C++を嫌うのは彼だけではない。STLやBoostを潜在的に不安定で非効率にした原因がC++だと考える開発者も多い。しかし、C++の需要がなくなることはない。Diceの記事では、C++はそれほど嫌悪するべきものではないとJeff Cogswell氏が主張している。「実際には一度しか使用しないのにも関わらず、複数の継承を重ねて再利用可能なクラスを作成するといった、過剰な設計をこれまでに何度も目にしてきている。」と、Cogswell氏は語る。「しかしこれは例外であり、標準ではないと主張したい。適切に使用すれば、一般的なプログラミングや、C++のより高度な機能を使用したプログラミングで、大きな利益が得られる。」とのこと。Linusの発言は行き過ぎだったのだろうか。

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • classとか設計に絡むものが言語仕様に取り込まれると、設計スキルが如実にコードに出る。
    適切に使える人と格差が出やすいので、それでビジネスをする人にとって有利な言語かもしれない。
    格差があれば、大きな利益を得られる訳だ。

    • C++に限らず (スコア:3, 参考になる)

      by SteppingWind (2654) on 2015年03月14日 15時11分 (#2777566)

      一つの言語で低レベルのシステム記述から, 抽象度の高いアプリケーションまで対応させようという試みは, 古くはPL/IからAdaなど, 総じて良い結果を出したとは言えないですよね. その中ではC++はまだうまくやっている方だとは思いますが.

      昔から, 銀の弾丸では無いですけど, 一つの言語で全ての用途をカバーするという欲求は強いんですが(その昔にはCOBOLで経済学的な数値解析をしたいというニーズも有ったらしい), むしろ用途に応じて数個の言語を使い分ける方が, 初期投資は大きくても最終的には幸せになれると思います.

      個人的にはベースとなるCに, Lua [lua.org]の様な軽量スクリプト言語, それにPython, Rubyの様なリッチなスクリプト言語の組み合わせぐらいがバランスが取れていそうと感じますが.

      親コメント
      • by plauda (46850) on 2015年03月14日 18時02分 (#2777643)

        Luaなどの組み込み言語を使う用途の場合、手続き的処理を記述するのが主目的なので、
        モージュール内部でカプセル化とか、ポリモーフィズムとか、オブジェクト指向言語の持つ性質は
        コード中にあまり必要とされないでしょうね。

        それに、組み込み言語を使うような所は、末端のエンジニアがコーディングする部分だと
        思うので、言語仕様の拡張性の高さより、「必要十分なシンプルさ」といった性質の方が
        メリットがありそうです。言語仕様がシンプルなら、プログラムバグの傾向も把握しやすそうです。

        実のところ、カプセル化とか、ポリモーフィズムといった性質って、モジュール単位(実行プログラムやライブラリ)には既に備えている性質です。
        今回はCとC++の話なので、カプセル化とか、ポリモーフィズムといった性質を
        モジュールより細かいソース単位の粒度で扱いたい立場の人に対する話ですね。
        なので、微妙に数個の言語の話は微妙に路線が違うかもしれません。

        「あまねく関数、構造体、技術者にオブジェクトの光あれ。」と言った時、
        暖かい救いのある光に感じるか、あるいは、憎しみの光に感じるか。それは経歴次第かな。
        モジュール・ライブラリ単位の抽象化というのは、どこもあまり失敗しない話でしょうが、
        モジュールより細かい単位の抽象化というのは、初期の段階(新規に参入する分野では特に)で子細にオブジェクト(凝集度 [wikipedia.org]、ライフサイクル、拡張性など)を考慮して、理想的な形で表現するのは難しいことですし、
        それなら、構造化プログラミング的なアプローチで、適切に関数分割して、ライフサイクルは基本関数のスコープに合わせて書くぐらいの伝統的なやりかたの方がシンプルだと考え方もあるかなと思います。

        親コメント
    • by Anonymous Coward on 2015年03月14日 14時03分 (#2777527)

      classを普通に作るにもEffective C++またはそれ相当を読まなきゃならないのがC++。
      もちろん読むやつなどいないので、むちゃくちゃなclassができる。
      インスタンスをコピーすると終了時にSEGVで落ちるプログラムとか。
      「コピーすることは想定していませんでした」だって。ならそう書けよ。

      こういう馬鹿を想定していないのは古臭いと思う。
      分かりやすくて良い?

      親コメント
      • 最初からD言語のようにstructとclassで値型、参照型と分けていればマシだったんだ、
        それかユーザー定義のデストラクタがあるクラスには、コピーコンストラクタ、代入演算子を自動生成しないとでもすれば良かったものを、

        C++は割となんでもできるが、上手くやる方法は定義しないor支援しない言語だよねぇ。C++11以降は多少改善されたけど。

        親コメント
      • by Anonymous Coward

        ゴミコードを増加させる例えとして良い思いますが、ポインタの功罪とも言えるので悩ましいです。

    • 「馬鹿とはさみは使いよう」って事ですかね

  • by Anonymous Coward on 2015年03月14日 13時17分 (#2777505)

    古臭い言語だと思う。
    土台が言語仕様貧弱なC言語なのに、無理して増築した感がある。
    土台から変えた言語を使うべき。

    • by Anonymous Coward on 2015年03月14日 13時50分 (#2777520)

      古臭いC言語ですがコーディングの仕方によって、例えば文章のような関数名と構造体を巧くインスタンスとして使えばC++以上のオブジェクト指向な綺麗なコードが仕上がると思います。
      昔、C言語の関数名制限に8文字以下というのがあったときは、相当苦労していたでしょうね。

      C++では、練りきれない仕様での無意味なクラス化とか、IDEと連携しないとメンバ関数を見失うとか、何でもかんでも標準化してみるとか、そんなことばかりやっていれば構造化プログラミング世代以下の汚いコードになるでしょうね。

      # ファイル拡張子をcppと書いて内部ではCで書いている私です
      # ガンプラはどう作ろうと自由だ

      親コメント
      • by Anonymous Coward

        C言語でも、C89で書かれたコードは微妙ですね。GNU拡張の一部が取り入れられたC99は綺麗なコードが多いですが、長年Microsoftが未対応を貫いていてC99普及の障害となっていました。

        # 最近やっっっっっっっっっっっとC99に対応しました>Microsoft

      • by Anonymous Coward

        > 古臭いC言語ですがコーディングの仕方によって、例えば文章のような関数名と構造体を巧くインスタンスとして使えばC++以上のオブジェクト指向な綺麗なコードが仕上がると思います。

        C言語で書いオブジェクト指向のコードって、関数ポインタだらけなイメージなんですが、
        C言語で書いたC++以上のオブジェクト指向な綺麗なコードっていうのが、
        どんな感じなのか、参考になるURLとか教えてもらえると嬉しいです。

        > C++では、練りきれない仕様での無意味なクラス化とか、IDEと連携しないとメンバ関数を見失うとか、何でもかんでも標準化してみるとか、そんなことばかりやっていれば構造化プログラミング世代以下の汚いコードになるでしょうね。

        コードが汚い云々は言語仕様よりも設計、コーディングする人次第っしょ。

        • by Anonymous Coward on 2015年03月14日 17時50分 (#2777638)

          AC(#2777520)です。

          > C言語で書いオブジェクト指向のコードって、関数ポインタだらけなイメージなんですが、
          まあ確かにそうですね。 constやrestruct修飾子を巧く使えば、最近のコンパイラがある程度のミスを見つけてくれるのは助かります。
          ポインタを使うことによる危険性も確かにありますが、コンパイラに全て任せて良いのかとの懐疑的であったりします。まぁ、任せたほうがコーディング的に楽ですが。バッファとかをSTLで確保した場合、いつ開放されるかはSTLの実装次第なので、やはりある程度はプログラマも認識は必要だと思いますね。あ、C++11では開放タイミングが指定できるようになったんでしたっけ。

          昔、こんな提唱もありましたね。結構気に入ってます。
          C-language's Object Oriented Language
          http://www.sage-p.com/process/cool.htm [sage-p.com]

          > C言語で書いたC++以上のオブジェクト指向な綺麗なコードっていうのが、どんな感じなのか、参考になるURLとか教えてもらえると嬉しいです。
          組み込み系でよいか解かりませんが、OpenBSDのIntelのデバイスドライバなんかは巧いことやっています。純潔LinuxやFreeBSDだとフレームワーク化されているので、かゆいところが見えないところがありますね。
          http://ftp.cc.uoc.gr/mirrors/OpenBSD/src/sys/dev/pci/ixgbe.c [cc.uoc.gr]
          http://ftp.cc.uoc.gr/mirrors/OpenBSD/src/sys/dev/pci/ixgbe_x540.c [cc.uoc.gr]
          ※ 実際はいくつかのデバイスを切り替えているので、さらに数ファイルで構成されています。
          関数宣言とか書き方が微妙なのはデバイスドライバということでご理解ください。

          > コードが汚い云々は言語仕様よりも設計、コーディングする人次第っしょ
          まさにそうですね。

          # ガンプラはどう作ろうと自由だ

          親コメント
    • by Anonymous Coward

      土台から変えた言語を使うべき。

      具体的には?

      • by Anonymous Coward on 2015年03月14日 17時28分 (#2777623)

        別ACですが、Rust [rust-lang.org]が最右翼じゃないでしょうか。

        C++を部品とり程度に扱い、現代の知見をもとにCの精神をそのまま残して発展させたのがRustです。

        • 型システムに、変数の生存期間の概念を統合。生存期間を越えるような変数代入、すなわちダングリングポインタはコンパイル時エラーとなる
        • 値型のスタックアロケーションが基本で、mallocはスタックアロケーションからの参照を根として生存期間コントロール。
        • GC(参照カウントベース&マーク&スイープ)は、あるにはあるが、おかざり。使わないのが基本。
        • ムーブセマンティクスと貸出の概念によりエイリアスの存在がコンパイル時エラーとなる。
        • 上記はマルチスレッド配下で重要で、「非決定性」による不定値の存在がコンパイル時エラーとして排除される。
        • とにかく、意図的だろうが偶然だろうが、メモリエラーを言語仕様として書くことができない。(unsafeとffiをつかった場合を除く)
        • 現代的な言語としてのつくり。パッケージシステム、ビルドシステム、など。
        • 「未定義動作」を避ける。「未定義動作」をこれでもか!というぐらい綿密に定義するほど非生産的なことはない。usizeisize万歳。
        • Haskellライクな型クラス、関数型プログラミングも可能。それが嫌ならtrait objectでvtableも使えてOOPっぽいこともできなくはない。
        • 悪名高きプリプロセッサはなく、構文を扱うマクロがある。コンパイラプラグインもある

        Rustは「自分の足を撃てないC」です。正しい進化だと思う。
        もっとも、敷居は高いです。

        親コメント
    • by Anonymous Coward

      Cは行間が読めない言語
      C#は行間が読める言語

      Cの仕様を引きずるC++、Objective-Cは前者。
      Javaはどちらかといえば後者だが冗長的な記述が多くなる傾向がある。
      PHPなんかも型の扱いが大らかすぎて前者。

      SwiftやScaleはまだ触ったこと無いので除外

      但しC#でもクエリ式はダメ

  • by Anonymous Coward on 2015年03月14日 18時02分 (#2777642)

    理解するにはあまりにも大きすぎる

  • by Anonymous Coward on 2015年03月14日 13時31分 (#2777511)

    LinuxはひどいOSだ 水準以下のユーザーが数多く使用していることで、またさらに簡単に完全なゴミを作り出せるようになっている点だ
    とも言えるわけだしな
    問題なのは水準以下のほうだろう
    批判するならカーネルに使われてるC言語はどうなんだ?
    あれだって水準以下のプログラマーが作ればひどい魔物に成長するものだ

    • by Anonymous Coward

      Cはそれでも枯れているからじゃね?
      と爺プログラマは思っているだろう
      あと言語にfail safeが取り込まれていない言語は若者は取り込みにくいだろう

    • by Anonymous Coward

      今時はC言語なんてわざわざ使う人に水準以下の人なんて少ないんじゃないか?

      • by Anonymous Coward

        それ言ったら今時C++を使う人なんてって話にならないか

    • by Anonymous Coward

      どっちも凶悪な魔物が作られるけど倒しやすい方といえば経験則的には…う、うーん。どっちも大変だな…

    • by Anonymous Coward

      考えてみると、「メンテナンスさせられた経験」が、その言語のイメージに強く関わっているようなw

      Cってアホみたいに巨大な関数書いたり、機能してないコーディング規約を遵守(読み辛さに貢献している)してる
      コードを扱った思い出ばかりで、すこぶるイメージが悪い。
      当然全てのプロジェクトがそうではないのだけど、なんかPHPに似た精神のプログラマがそこそこいた気がする。

      C++はなんだかんだで、関数は短くしよう、プログラム部品は一定の単位に整理して管理しようという
      常識は感じるプログラムが多かったので、ハマる事はそれなりにあっても許せるレベルだった。

      • by Anonymous Coward on 2015年03月14日 17時38分 (#2777630)

        >機能してないコーディング規約
        再帰呼び出し禁止→スタックのことを考えれば、やむなし
        goto禁止→分からなくもないが、エラー処理にはgotoが欲しい
        関数末尾以外のreturn禁止→理不尽

        親コメント
      • by Anonymous Coward

        言語的な問題じゃないけど。
        初期の(だと思うけど)ソースコードデバッグで関数シンボル名が無茶苦茶で投げた経験からC++は受け付けなくなった。

  • by Anonymous Coward on 2015年03月14日 14時03分 (#2777528)

    実際に自分が目にした範囲で言えば、Javaが随一だと思う。
    まぁ、それほど多く使われているからって部分もあるけど。

    • by Anonymous Coward on 2015年03月14日 14時38分 (#2777548)

      確かにJavaのプロジェクトはひどいの多いし、Javaに低レベルな技術者もっていかれるからC++にはそれなりのPGが揃うんでC++のがマシに見えるかもしれない。
      でも、本気のC++のヤバさはそんなもんじゃないよ。一瞥して謎の言語に見えるほど別物になることもあるし、普通に見えて至る所罠だらけで簡単な修正が予想外の影響を引き起こす怪物にもなる。

      親コメント
  • by Anonymous Coward on 2015年03月14日 14時21分 (#2777540)

    iosreamの是非は置いといて
    ループの中にィテラル書式のprintfが鎮座とか邪悪なコードを最短距離で構築できるのはC言語の方だろう

    • by Anonymous Coward

      型安全じゃないしな

    • by Anonymous Coward

      でも、iostreamの遅さを見るとなぁ…

    • by Anonymous Coward

      高々十数文字程度の文字列を処理するのに、いまどきそんなに高コストな処理なのか?

  • by Anonymous Coward on 2015年03月14日 14時41分 (#2777551)

    taro-nishinoの日記: Linus氏のC++に対する最近の否定的見解
    http://srad.jp/~taro-nishino/journal/509450/ [srad.jp]

    Linus氏のC++否定論は、C++というよりも、オブジェクト思考言語全般に当てはまります。読まずに批判・評価する人は、まず読みましょう。
    例えば、Linus氏はこういうことを言っています。

    「良いコード設計は、いかにデータが移動するか、いかにデータを秩序立てるか、いかにデータを見つけ、他のデータと関連付けるか、について考えが次々と思い浮かぶ。
    だが、OO言語は、オブジェクトが重要であり、オブジェクトに関連付けられたメソッドを持つべきだという手段を考える傾向にある。まさに馬鹿げた話だ。一つのオブジェクト(又は、ある型のオブジェクトの当り前なコレクション)が本当の関心事ではない。
    関心すべきは、異なる型の異なるオブジェクトが相互作用し、ロッキングルールを持つ等々の時なのである。その時点で、重要なのは一つのオブジェクトではもうないのだから、"オブジェクトインターフェイス"を隠蔽しようとするのは絶対に間違っている。」

    • 本来のオブジェクト指向のオブジェクトは、メッセージの送受信により処理を定義するものなので、プロセスやスレッドに近い。
      オブジェクト=スレッドを明確にしたのが並列処理のアクターモデル。

      大抵のオブジェクト指向言語のオブジェクトはメソッドが定義できる抽象データ型で、f(obj)をobj.f()として書けるシンタックスシュガーのようなものだから、
      オブジェクト指向的な設計を行っても、メッセージ送信が関数呼び出しなので、手続き的に密結合になって、並列処理との相性が良くない。

      親コメント
    • リーナスにしろ、ストールマンにしろ、なんでこう攻撃的で過激なことを言っちゃうんだろう。
      コンピュータの自由を守るためには、これくらいの攻撃性は必要なのだろうか?

      親コメント
    • by Anonymous Coward

      >"オブジェクトインターフェイス"を隠蔽
      これは何を言いたいのかさっぱりわからん。
      インターフェイスは隠蔽すべきでないし、むしろ積極的に明確にするのが普通。隠蔽すべきは、実装などの詳細部分。

      • > インターフェイスは隠蔽すべきでないし、

        Linus の言っている "オブジェクトインターフェイス" というのは
        オブジェクト指向プログラミング言語なるものが
        オブジェクトなるものを扱うためのメモリ管理機構等に
        対するインターフェースのことでしょ。

        で、"隠蔽" というのはオブジェクト指向プログラミング言語では、
        こういった管理機構が暗黙のうちに機能するように言語仕様が
        設計されていることをいってんだろうと思う。

        親コメント
      • by Anonymous Coward

        言ってることが逆だよね。
        OOはオブジェクトそのものが重要ではなく、インターフェースやオブジェクト同士の関係が重要となっている。
        OO (正確にはADT)より前は、データの中身やその表現方法などが重要だった。というか、インターフェースなどの上位層とその層を明確に分離できてなかった。

        • by Anonymous Coward on 2015年03月14日 16時10分 (#2777587)

          リファクタリングの話のときにもあったけど、
          Cだと

          struct  A {
          ...
          };
          struct B {
          ...
          }
          void connectAB(A* aA, B* aB) {
          ...
          }

          をオブジェクト志向だと、

          class  A {
          ...
          };
          class B {
          ...
          };
           
          void A::connectB(B* aB) {
          ...
          }

          にするのが気に入らないってことでしょ。コンパイラにとってはともかく、カプセル化することによって、わかったようなわからないような感じになる。

          親コメント
        • by Anonymous Coward

          並列プログラミング時代に重要なのはデッドロックを防ぐためのロッキングルール(AB-BAデッドロックを防ぐためのロック階層)を正しく保つことにあります。
          オブジェクト指向の問題は、振る舞いの隠蔽によってロッキングルールの守られているかが見えにくくなっていくことにあります。

      • by Anonymous Coward

        > When it gets interesting is when different objects of
        different types interact, and have locking rules etc. And
        at that point, trying to encapsulate some "object interface"
        is absolutely the wrong thing, because it's not about a
        single object any more.

        「オブジェクトインターフェイス」"を"ではなく、"に""へ""で"隠蔽といったところでしょう

    • by Anonymous Coward

      どこに付けるか迷いましたけど
      Linus氏のいう所のオブジェクトは(C++は詳しくないので)Javaでいう所のインスタンスの事です、多分。
      Cより粒度の荒い中途半端なクラスしか作れないくせに、メモリ上で直接操作できないようになっている、
      そして言語仕様でクラスやその他の構文によって意味的には記述できても機能的にはよく分からない事をしている。
      だからシステム記述言語としては相応しくないと。
      それ以外の事に使うのならVM系言語である機能が無いのでCもどきであるC++である必要は無いので有り得ない。
      という話だと思われます。

      • by Anonymous Coward

        >Cより粒度の荒い中途半端なクラスしか作れないくせに、メモリ上で直接操作できないようになっている、

        どういうこと?

    • by Anonymous Coward

      >「良いコード設計は、いかにデータが移動するか、いかにデータを秩序立てるか、いかにデータを見つけ、他のデータと関連付けるか、について考えが次々と思い浮かぶ。

      これが、作った人にしか思い浮かばないから、OOPを使うんだと思うけどな。

  • by Anonymous Coward on 2015年03月14日 17時02分 (#2777610)

    行為主体が物ではなく人間(コンピュータ)なのだから、
    「AがBと何々する」
    より
    「私がAとBを何々する」
    と言う記述が人間には自然でしょう。
    よってオブジェクト指向的記述はいまいちだと思われます。

    • by Anonymous Coward

      それはoopの問題ではなく
      interface 私 {
              void 何々(A a, B b);
      }
      というように設計すべきという話ですね。
      そしてコンピュータは人間ではありません。

typodupeerror

犯人はmoriwaka -- Anonymous Coward

読み込み中...