C++ の int はレジスターイメージ classはメモリーイメージ
C++ の int はレジスターイメージ。 だから CPUが32Bitなら 32Bit 64Bitなら64bitがint
そして レジスターが不足した時に自動的にメモリーに退避してくれるのが int
もう今では register int x;
という書き方は使われないでしょうが レジスター変数を最適化で期待するのがint;
他方 structは 何をどうやってもregisterには なれないことが基本の(例外を除く) メモリー型。
classは そのstructにvtableが付き コピーコンストラクターが指定できるもの。
つまり intからintへのコピーは ほぼゼロコストか レジスター1個分のメモリーのコピーコスト
structからstructへのコピーは メモリーからメモリーへのコピーコスト
structのポインターからポインターへのコピーはintからintへのコピーコストと同じ。
こういう その 表現が CPUにとって どれだけのコストであるかを 考えるのは
時代遅れ なんですが C/C++の 根源 であり 歴史であり 存在意義 なので 忘れないで下さい。
>他方 structは 何をどうやってもregisterには なれないことが基本の(例外を除く) メモリー型。
>classは そのstructにvtableが付き コピーコンストラクターが指定できるもの。
2点違います。
structとclassに関して。structとclassはデフォルトの公開範囲が異なるだけで他は全く同じものです。
vtableに関して。仮想メンバ関数を持つstructとclassが、その内部実装によってはvtableを持ちます。
>structのポインターからポインターへのコピーはintからintへのコピーコストと同じ。
必ずしも同じとは限りません。
というのも、ポインタのサイズとintのサイズが異なるケースがあるからです。サイズが異なればコピーコストも異なります。
それは規格でも認められていますし、そういう実装(LP32,LLP64,LP64など)が存在します。
ポインタを整数として安全に扱うために、intptr_tが用意されているぐらいですし、sizeof(void*) == sizeof(int)を期待しては絶対にダメです。
>こういう その 表現が CPUにとって どれだけのコストであるかを 考えるのは
>時代遅れ なんですが C/C++の 根源 であり 歴史であり 存在意義 なので 忘れないで下さい。
コストを考えるのは時代遅れではなく大切です。
だからこそ、正しい知識が必要です。
まず 実装上はstructとclassは違います。structはvtableを持たないことがありえます。
またstructはコンストラクタを持つことが出来ますが、class publicを書くべきです。
次に ここで言っているコストとは O(n)の事です。 メモリーコピーは外部へのI/Oを意味しますがレジスターは1クロック程度の差しかありません。
>> まず 実装上はstructとclassは違います。structはvtableを持たないことがありえます。
RiSKさんが仰っているとおり、structとclassは公開範囲を除いて全く同じです。structがvtableを持たないことがあり得るように、classにも全く同じようにあり得ます。
プログラム中のコードのclassをstructに、あるいはその逆に変えてみてもバイナリは変わらないでしょう。
言語仕様上、公開範囲の解釈が異なるだけでバイナリに落とす段階では全く同じです。
それは最適化を期待した場合では?
意味論的にはstructは本来 vtableをもたない事を期待されていて(C言語時代からの引き継ぎ)
classは本来vtableを持つことを期待されていて declspec(novtable)などのキーワードで明示的に落とす言語もある。
ここで言っているのは 意味論 というか 全く同じなら classなんていらない。
C言語時代から 引き継がれてきた 歴史的経緯が違う。
最適化を究極的にかけていけばおなじになるだろうけれども
意味があるからキーワードが違うのに それを無視しちゃ駄目でしょ。
それをいったら 32ビット環境におけるint32_t と intは同じだみたいな議論だよ。
吐き出すバイナリはおなじになる。でも64bitへの対応という意味がある。
shortやlongなんていらない int32_t int16_tがあればいいじゃないか!みたいな議論。
そこに至るまでの 歴史的経緯が違う。
僕が言いたかったのはclassもstructもclass keyが異なるどちらも同じ「クラス」であると、言いたかっただけです。最適化などは全く関係ない、言語仕様の話です。
意味を無視しているのではなく、規格で公開範囲しか違わなくて、どちらもクラスであると書いてあるのでvtableがあるないはclassとstructで全く違いは無く、その文面は間違っているということです。
>> classは そのstructにvtableが付き コピーコンストラクターが指定できるもの
この部分が現規格においては正しくないということです。
C++としては誤った解釈であると、それ以上でもそれ以下でもありません。
規格の文面上も、コンパイラの実装上(最適化の有無問わず)もstructとclassはどちらも同じ”クラス”です。
デフォルトの公開範囲が異なるだけで他は全く同じものです。
規格書もコンパイラの実装もそうなっています。
規格からstructとclassで異なっている部分を引用します。
11 p3
Members of a class defined with the keyword class are private by default. Members of a class defined
with the keywords struct or union are public by default.
11.2 p2
In the absence of an access-specifier for a base class, public is assumed when the derived class is defined with
the class-key struct and private is assumed when the class is defined with the class-key class.
これ以外は、同じものとして11全体で定義されています。
そして、コンパイラはその通り正しく実装しています。
> 意味論的にはstructは本来 vtableをもたない事を期待されていて(C言語時代からの引き継ぎ)
> classは本来vtableを持つことを期待されていて declspec(novtable)などのキーワードで明示的に落とす言語もある。
> ここで言っているのは 意味論 というか 全く同じなら classなんていらない。
> C言語時代から 引き継がれてきた 歴史的経緯が違う。
C++の産みの親Bjarne Stroustrupがその点を説明しています。
structとclassが同じであることについて、
「
(snip)structとclassを別の概念にすることを選ばなかったのだろう?
私の意図は概念を一つにすることだった:
(snip)structが”Cと互換性”のテーマに
属して、classが”C++と高度な機能”に属したら、ユーザグループが二派に分か
れ、犬猿の仲になってしまうだろう。
」
「C++の設計と進化」94ページからの引用。これが正しい歴史的経緯です。
なおCと互換性のあるクラス(構造体)が必要な場合は、standard-layout classあるいはPODの条件を満たしたクラス(構造体)を作ります。
当然structでもclassでもそれが保証されます。