質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • C

    3701questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    3457questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • オブジェクト指向

    284questions

    オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

オブジェクト指向のメモリ効率

解決済

回答 4

投稿

  • 評価
  • クリップ 4
  • VIEW 4,871

strike1217

score 554

オブジェクト指向ってメモリ効率が悪くないでしょうか??
オブジェクト指向についてまだ理解が不十分なので使い方がイマイチよくわかっていません。

「メモリ効率が悪いのでは??」と思ったのはメソッドです。(メンバ関数)
(ここで言うメソッドと関数は同じものとしますね。)

以下にテストした簡単なサンプル。

#include<iostream>

class test{
    public:
        void func(int&& y){
            std::cout << y << std::endl;
        };
};

class same_func{
    public:
        void func(int&& y){
            std::cout << y << std::endl;
        };
};

class same_func_keishou : public same_func{
    public:
        void other_func(int&& x){
            std::cout << x << std::endl;
        };
};

int main(){
    test check;
    check.func(1);

    same_func same;
    same.func(2);

    same_func_keishou keishou;
    keishou.func(3);
    keishou.other_func(77);
    return 0;
}


以下、逆アセンブルした関数呼び出し部分です。

 e8 b4 00 00 00          callq  980 <_ZN4test4funcEOi>

 8e1:   e8 d6 00 00 00          callq  9bc <_ZN9same_func4funcEOi>

 8fb:   e8 bc 00 00 00          callq  9bc <_ZN9same_func4funcEOi>

 915:   e8 de 00 00 00          callq  9f8 <_ZN17same_func_keishou10other_funcEOi>

全く同じ定義の関数が所属しているクラスが異なるだけで、2つの関数のための領域がメモリ上に確保されることになります。
「継承している場合は複数定義されることはない」ということのようです。

以下のような質問を見つけました。
C++でのクラスのメンバ関数が占める容量が知りたい

All instances share the same member function code.

まぁ・・・これはそうでしょうね。
インスタンスごとに異なる関数として定義されては、流石に効率が悪すぎます。

オブジェクト指向と10年戦ってわかったこと

継承は親クラスの機能を受け継ぎますが、これは開発効率を上げるための優しさ的仕様であり、継承の本質はインターフェイスなのです。もしあなたが継承の本質を「機能の受け継ぎ」と勘違いした途端、オブジェクト指向はあなたに牙を剥くでしょう。

むむ??
自分は今まで「継承」を「同じ関数を再度作るの面倒だから」・・・とか「この関数があれば便利だから」という理由で継承を利用していました。
ところが、この機能を受け継ぐという考え方はどうもダメみたいです。
(同じメソッドを使う場面が結構ありました。)

そうすると、同じメソッドもしくはif文などの条件分岐を少し加えるだけで、1つの関数にまとめられるような場合、どのようにしてプログラムを作れば良いのか??という疑問があります。
これは、C++に限った話ではないですね。

アプリケーション開発みたいに、最近のメモリは大量なのでこれくらいは大丈夫・・・という気がしますが・・・
OS開発や組み込み系の低レイヤーでは、同じ関数が別の物として複数定義されているのは、ちょっと効率が悪いですよね??
「塵も積もれば山となる」みたいな・・・

STLにそのようなメソッドがあるかどうか不明なのですが・・・
std::vector と std::stringについて試しに調べてみましたが、全くの別物でしたね。

//std::vector::push_back()
#if __cplusplus >= 201103L 
void
push_back(value_type&& __x)
{ emplace_back(std::move(__x)); }     

//std::string::push_back()
      void
      push_back(_CharT __c)
      {
        const size_type __size = this->size();
        if (__size + 1 > this->capacity())
          this->_M_mutate(__size, size_type(0), 0, size_type(1));
        traits_type::assign(this->_M_data()[__size], __c);
        this->_M_set_length(__size + 1);
      }


ライブラリなどでこの・・・「同じ関数が別物として定義される」ものを作るとメモリ効率が下がりますよね。
特に、C++のような低レベルのプログラミングをジャンジャンできるような言語だとメモリを無駄遣いするわけにはいかないかと思います。

STLを眺めていて以下のような記述を目にしたことがあります。
(ちょっと違うかもしれません。)

push_back(){
    _Base::push_back();
}


うーーーん。ちょっと微妙。
カプセル化に反する??
何度もよく使うようなメソッドをまとめといて、それを呼び出している感じですね。
これだと、C言語でオブジェクト指向プログラミングをしているのとあんまり変わらないような気がします。(Linux Kernelみたいな)

同じメソッド、あるいはかなり近い、似たようなメソッドを使いまわしたい場合、どうすればよいのでしょうか?

メモリ効率のモヤモヤ感とオブジェクト指向の考え方がちょっと難しいですね。
ポリモーフィズムなどはメモリを食いそうで仕方がないとという感じがしますが、Cに比べるとちょっとメモリ効率が悪い感じですかね。

分かる方教えてください。
環境は、Linux g++ でやりました。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+17

同じメソッド、あるいはかなり近い、似たようなメソッドを使いまわしたい場合、どうすればよいのでしょうか?

さして容量が逼迫しているわけでもない状況下で、「容量的な意味で」使いまわしたいのであれば、その考えを捨ててください。僅かな容量を節約することによって得られるメリットと、手間やバグのリスクを考えれば、多くの場合は削減するメリットがありません。

ポリモーフィズムなどはメモリを食いそうで仕方がないとという感じがしますが、Cに比べるとちょっとメモリ効率が悪い感じですかね。

「はい、そのとおりです」以上のコメントはありません。テンプレート機能もあくまで「型だけ違う関数やクラスを、手間なく作れる」というものを意図したものなので、容量効率なんてことは基本的に考慮していません

特に、C++のような低レベルのプログラミングをジャンジャンできるような言語だとメモリを無駄遣いするわけにはいかないかと思います。

容量に制約がある場合は、C的な書き方に移ることもできる、というのがC++の魅力(魔力?)でもあります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/17 13:18

    「その考えを捨ててください。」
    というのは、「メモリ容量について気にするな!!」という意味です?

    「その」といういのはメモリ効率についてでですよね?

    「容量効率なんてことは基本的に考慮していません。 」
    あ・・・そうなんですね。

    キャンセル

  • 2018/07/17 13:21

    「容量に制約がある場合は、C的な書き方に移ることもできる、というのがC++の魅力(魔力?)でもあります。」

    な・なるほど!modern C++ と レガシーなCをうまいこと使い分けるんですね。

    キャンセル

  • 2018/07/17 14:02

    strike1217 さん
    メモリー容量を意識する必要があるなら、そういう意識が反映できる言語を選択するということになりますから、選択した後に文句を言っても、ってことですね。

    キャンセル

  • 2018/07/17 14:28

    すいません。文句のつもりではありませんでした。
    C言語の考え方がちょっと抜けなくて、C++でも同じようにメモリ効率を考慮するのかな?・・・というのが疑問だったので!

    キャンセル

  • 2018/07/17 14:34 編集

    文句というのは単なる表現のつもりです。
    メモリ容量をシビアに制御する必要があるなら、言語特性によるトレードオフなんかは事前に考慮すべきことで、順序が違うというのが伝えたい事です。
    単に知りたかった故の質問であったということは理解しました。

    キャンセル

  • 2018/07/17 14:39

    あ!なるほど!
    わかりました。

    キャンセル

  • 2018/07/24 22:23

    補足しますと、現状、家庭用ゲーム機ぐらいしかメモリ容量を気にする必要性は薄いです。加えて、オブジェクト指向はAndroidアプリ(made in java)になると、ルールと実装の明確化を可能にした側面もあります。これにより、ルール側でメモリを圧迫しないような書き方を指定できますので、規模が大きく複雑なものですと、かえってメモリ消費を抑えてくれます。

    キャンセル

  • 2018/07/25 02:58

    この程度のオーバーヘッドが問題になる環境って実は今はほぼ存在しないと思います。ゲームとかでは60fpsとか実現するのではnewするのが重いので、配置newっていうのを使ってあらかじめ確保したでかい領域をちまちま指定して使うことによりゼロオーバーヘッドで性能を劣化させることなく使ってるっていうのはたまに聞きます。

    キャンセル

+4

push_back(){
    _Base::push_back();
}

やはり、これを基本に工夫していけば良いのだと思います。

あるいは、フリー関数(非メンバ関数)で書いておいて必要に応じて呼び出すという手もあります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/17 19:01

    ああ〜〜。
    やはりそうですよね。
    それぐらいしか思いつかないですね。

    キャンセル

  • 2018/07/17 19:06

    サンプルの複数のメソッドの実装が
    std::cout << y << std::endl;
    となっている時点で,「ostream.operator<<(int) の中身」という"同じ処理"をまとめることが既に達成できているように見える……

    キャンセル

  • 2018/07/17 19:09

    あくまでテスト用に作っただけなので、実際にはもっと複雑な関数の場合を想定してください。

    キャンセル

  • 2018/07/17 20:48

    どれだけ複雑だろうが,何らかの単位で{同じ,ほとんど同じ}処理をまとめたいのですよね? ならば,そのまとめたい部分に関して,こういうことをするだけなんじゃないの?ということを言っているのですが.

    キャンセル

  • 2018/07/17 22:54

    あ、そういうことですか。
    失礼しました。

    キャンセル

  • 2018/07/25 07:58 編集

    完全に同じメソッドならMixinにするとかね。あ、メモリ効率が良くなるかはわかりませんが。

    キャンセル

+3

Donald E. Knuthの格言に、

すべてとは言わないまでも、ほとんどすべての諸悪の根源は「早すぎる最適化」にある。

と申しますが、メモリ容量が実際に問題になってからメモリ最適化を考えたら良いんじゃないかなあ。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/24 19:12

    なるほど!早いうちからメモリ効率など考えなくて良いということですかね。

    キャンセル

  • 2018/09/26 09:55

    そうです。
    そのコードのメモリ効率が全体の性能を悪化させている、ということがプロファイラによって明らかになってから最適化に乗り出すので良いのです。

    もうひとつの格言。

    プログラムの処理時間の大半は、コードのごく一部に集中している。
    逆に言えば、その「ごく一部」以外を最適化することは、プログラマーの時間の浪費である。

    キャンセル

+2

たとえC言語でも、同じ動作をする関数を一つにまとめる、ような最適化するコンパイラは見たことないですが

        void A(int y){
            printf("%d",y);
        }
        void B(int y){
            printf("%d",y);
        }
        void C(int y){
            printf("%d",y);
        }


ってあったとき、関数を一つしか生成しないコンパイラってどっかにあります?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/17 13:16

    あーー。
    説明が下手ですいません。

    C言語のグローバルな関数を複数同じ物を定義するなんて場面はほとんどないですよね?
    その例だと、関数は1つで十分ですよね?わざわざ3つ用意する必要がありません。

    自分の質問はC++のオブジェクト指向、class内のメンバ関数についてです。

    キャンセル

  • 2018/07/17 13:21

    Cでも実現できていないものがオブジェクト指向だから実現しないのはおかしいというのは、ちょっと間違ってると思いますけどねえ

    キャンセル

  • 2018/07/17 13:29

    「関数を一つしか生成しないコンパイラってどっかにあります?」
    それは・・・おそらくないと思います。分かりません。見たことないです。

    コンパイラの機能の話ではないです。
    すいません・・・

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    Javaでは実装できるメソッドを持つenumについて

    Javaでは以下のように方向を管理するクラスDirectionが作れ、直感的に使えます。 public enum Direction { FRONT(0), RIGH

  • 解決済

    STLに対してObserverパターンを実現するには?

    例えばstd::vectorでpush_back等の関数が呼ばれた時に同時に別の関数を呼び出したいのですが、どうやって実現すればいいのか分かりません。 STLのクラスを継承する

  • 解決済

    2次元配列の値を関数の引数として渡したい

    タイトルの通り2次元配列で作ったものを関数の引数として渡したいです。また、2次元配列の大きさは固定ではありません。 私が書いたコードは、以下のようになります。 #inclu

  • 解決済

    【vector】vector.erase()を高速化したい

     解決済みですが、まだまだこんなのあるよ!という方のコメントを随時募集してます! 前提・実現したいこと タイトルの通り、C++のSTLコンテナの一つvectorクラスの"vecto

  • 解決済

    std::vectorの添字がうまく機能しません

    前提・実現したいこと 現在C++とSiv3Dで落ち物パズルゲームを制作しています。 発生している問題・エラーメッセージ std::vectorを使用して'Block'クラスを格

  • 解決済

    授業で扱われたプログラムが理解できません

    授業で他の生徒が書いたプログラムです。私にはまだまだ理解できません。これを紐解いていきたいのですが、まず、3行目の std::string name; ってどういう意味です

  • 解決済

    子クラスの関数を親クラスで使いたい

     前提・実現したいこと 子クラスの関数を親クラスで使いたい。 調べてみて似たような話をかなり見かけたのですが、内容をイマイチ飲み込めなかったので質問させていただいています。 よ

  • 解決済

    vectorを外部の関数から値を変更したい

     前提・実現したいこと ここにを質問の内容を詳しく書いてください。 (例)vectorクラスを用いて値の変換を外部でしたいです. vectorを配列のように扱っているのでアドレスを

同じタグがついた質問を見る

  • C

    3701questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    3457questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • オブジェクト指向

    284questions

    オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。