X



C++相談室 part138
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん (スフッ Sd9f-fGne)垢版2018/08/05(日) 18:02:36.57ID:DigzqJtZd
次スレを立てる時は本文の1行目に以下を追加して下さい。
!extend:on:vvvvv:1000:512

C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。

前スレ
C++相談室 part137
http://mevius.5ch.net/test/read.cgi/tech/1531558382/

このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.103【環境依存OK】
http://mevius.5ch.net/test/read.cgi/tech/1530384293/

■長いソースを貼るときはここへ。■
 http://codepad.org/
 https://ideone.com/

[C++ FAQ]
https://isocpp.org/wiki/faq/
http://www.bohyoh.com/CandCPP/FAQ/ (日本語)
VIPQ2_EXTDAT: default:vvvvv:1000:512:----: EXT was configured
0002デフォルトの名無しさん (ブーイモ MMa7-gYkF)垢版2018/08/05(日) 18:29:41.88ID:QdoPuPH9M
STLつかうと一気に実行ファイルサイズが10倍に?!

環境によるだろ。
俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力
ランタイムを使用するようにして使っているが、例えばstd::vectorを
使っても使わない時と比べ10Kほどしか増えない

すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。

C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。
とかいうエラーが出るんだけどこれってどうすればいいの?

#include <stdafx.h>
後死ね。

言葉が悪いな。それで教えているつもりか。
まぁヒントぐらいにはなったな。
うむごくろう。

---- テンプレ ここまで ----
0006デフォルトの名無しさん (オッペケ Sr03-s/wt)垢版2018/08/11(土) 09:08:09.59ID:9wE6Nq69r
rad c++ builderでファイルの入出力やドラッグ&ドロップ 簡単なdb操作は出来る様になったけど、もう一歩踏み出したいです


福岡当たりで勉強会みたいなのはないでしょうか?

大阪、東京でも有るなら飛行機使っていきたいです
0009デフォルトの名無しさん (ワッチョイ ed85-EM0A)垢版2018/08/28(火) 21:29:17.96ID:t/yKDZjb0
関数内にstaticつけたクラス変数定義した場合、
コンストラクタは関数を最初に呼び出したときだけ呼ばれると思います。
これはどういう仕掛けなのですか?どこかにフラグがこっそり用意されるのでしょうか。
0014デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/08(土) 15:23:29.92ID:Bduckbke0
virtualなデストラクタを持たないクラスを継承しているクラスを派生していない状態でコンテナ等に入れた場合、
エラーまたは警告にする方法ってある?

典型的な「デストラクタをvirtualにしろ」のケースであり、
安全性だけを取るのならそうすれば済むのだが、大量使用したいのでコストを限界までケチりたい。
可能であればコンパイラにチェックさせたい。


具体的に言うと、Matz曰く「実装が漏れてる」の典型的なケース、配列について、
長さと先頭のポインタをstructにして、各操作をそれに対するメソッドとして記述し、
スクリプト言語風に簡潔に書けるか試したい。
std::spanの再実装に近いので、そちらで言うと、
https://github.com/tcbrindle/span/blob/master/include/tcb/span.hpp
std::spanを継承して各種メソッドを生やし、(クラスM)
さらにそれを継承して以下3つのコンストラクタを持たせる。

クラスA. 型と既存ポインタと長さからの生成
クラスB. 型と長さを与え、allocaでの生成
クラスC. 型と長さを与え、heap上への生成

A,Bは問題ないが、Cはデストラクタでdeleteをする必要がある。
ここでstd::spanのデストラクタはvirtualではないので、(上記実装例の場合)
vector<C>をvector<M>等と間違えたら不味い。
このときに、警告またはエラーを発生させたい。
0015デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/08(土) 22:19:49.23ID:Bduckbke0
もう一つよろしく。

C++でkey/valueソートしたい場合は
・std::unordered_multimap等にコピーしてからstd::sort
・自前で<key,value>を含んだ構造体を用意し、それに < を定義して、コピーしてstd::sort
のどちらかって感じ?
ちょっとまどろっこしいので、もう少し簡単な方法無いかな?

doubleの配列をソートした際、何番目がどこに行ったか追跡したい。
.NETだと Array::sort(array0, array1) があり、
array0 に double の配列、
array1 に [0 ... N-1] な配列を指定しておけば、array1の結果で簡単に追跡出来た。
記法が原始的ではあるが、結果的にはこっちの方が楽で良かった。
std::sortで2つの配列を取る物があれば助かるのだが、なさそうだし。
boostも見たが、よく分からん。
0016デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/11(火) 19:14:32.80ID:85ZJZj420
抽象型のメソッドを使ったときにも型を失わず、派生型のままで返す方法って無いよね?
継承を使わず、テンプレートで展開するしかないか?
コード上で展開されるのが、多少勿体ないんだが。

>>14の実装で、
各種メソッドをクラスMに突っ込み、それを継承していると、
Cからメソッドを呼び出した際、どうしてもM&等の型しか返せず、
ダウンキャストがいちいち必要なのがウザイ。

具体的には、fromは既存の配列からコピー、sortはソートするメソッドとして、メソッドチェーンで初期化する際、

C& test = (C&)C( ... ).from( ... ).sort();

となり、fromやsortがM&を返すのでC&にダウンキャストする必要がある。
従来方式の初期化して使用なら問題はない。
コンストラクタは派生型を返し、メソッド群はM&で閉じているので。

A& test = A( ... );
test.from( ... ).sort();

メソッドをvirtualにすれば回避出来るはずだが、無駄にvirtualにしたくない。
B/C共に全く同一の関数で済むはずなので、可能で有れば共有したい。
諦めてB/C毎に同じ関数をtemplateで展開すれば出来るのは分かるが、これはしたくない。
何か方法有る?
0018デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/11(火) 21:47:24.91ID:85ZJZj420
>>17
オブジェクト指向ではMで閉じるというのが正しいと思いこんでるんだろ。
それは一面にすぎない。

JavaScriptではメソッドチェーンで型を失わない。
だから上記のようなことも平気で出来る。
勿論C++でも実装を別々にすれば出来るが、ダブる分無駄に膨らむ。
或いはvirtualにしても出来るが、これはポインタ一つ分データが膨らみ、呼び出しも遅くなる。
最適化した状態での記述方法がない。

今回、AとCの違いはデストラクタ内で解放するかどうかだけであり、
当然全てのメソッドは共有出来る。
順当なら継承が妥当だが、virtualにしないと型を失ってしまう。
(この点、全てvirtualであるJavaはオブジェクト指向原理主義としては筋が通っている)
0019デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/11(火) 21:53:29.04ID:85ZJZj420
ちなみに技術的には、super に対するキーワード derived が足りないのだと思う。
クラスM内で、

M& from(){ ... ; return *this;}

ではなく

derived& from(){ ... ; return *this;}

と出来て「呼び出した型」を返せれば全く問題ないんだが。
この辺のキーワードって無いよね?
0021デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/11(火) 22:17:09.88ID:85ZJZj420
C++がメソッドチェーンに向いてないのは確かだよ。
それ向けの文法も用意されてない。
多分「継承」に対して型を失うこと自体が間違いなんだよ。
C++はそこら辺が古い。

ただ、ダブって良ければtemplateで解決出来るのも確かだが。
0023デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/11(火) 22:31:38.02ID:85ZJZj420
>>20
あとついでに言うと、その選民思想はマジで止めろ。
C++だけの話でもないが。

というより最近「俺がやってる言語スゲー」な奴が多いのは何でだ?
一昔前は全員Cが出来、その上で他言語だったから、その手の争いは皆無だった。
それ以前にプログラミングがきちんと出来れば、後は文法だけの問題だから、
多言語化は容易だし、実際全く問題ない。
「俺の言語スゲー」でイキれる奴って文法しか見えない馬鹿のような気がするが。

C++はコンパイラ向けの文法ばかり多くて、本質的なプログラミング用の文法は多くない。
今回も、JavaScriptだと容易に実現出来るのに、C++だと記述出来ないだろ。
あまり他言語を馬鹿にしていると足をすくわれるぞ。
0025デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/11(火) 22:40:51.16ID:85ZJZj420
>>22
まあその通りだが、

C++: 記述出来ない
JavaScript: 動的型なのでそのまま書けるし、動作する
Java: 全部virtualだからそのまま書ける(ただし、これでいいのならC++でも書ける)
Go: 継承を廃止してしまったからそもそもこの問題は発生しない?
Rust: ちょっと見たがよく分からん

まあ俺はやっぱり、「継承」で親の関数を呼んだら型が失われるのは間違いだと思うよ。
仮に Z : Y : X と継承していたとして、
(Zの実体).(Xのメソッド).(Yのメソッド) とは出来ないでしょ。(Xのメソッドの時点でX&になるから)
これはメソッドチェーンする気なら使いにくい。
(これまでは居なかったから問題にならなかっただけ。バラバラに書けば出来るので)
0026デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/11(火) 22:45:25.78ID:85ZJZj420
>>24
とりあえず今はそれで実装してる。
それが16で言ってる
> 諦めてB/C毎に同じ関数をtemplateで展開すれば出来る
というやつ。
ただどう見ても無駄なので、可能で有れば実体も一つにしたい。
0028デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/11(火) 23:12:47.47ID:85ZJZj420
>>27
テンプレートは型毎に展開されるし、自明では?
むしろ通じない方が不思議だ。

仮に俺が言ったように19の表記が出来れば、
オブジェクトコードはその部分は半分で済むし、命令キャッシュのヒット率も上がる。
勿論C++でもvirtualにすればこれらの点は解決するが、
呼び出しが遅くなってデータオブジェクトもポインタ一つ分膨らむだろ。

今のC++では最適化したオブジェクトコードを吐かせる記述が出来ない。
0029デフォルトの名無しさん (ワッチョイ 7ab3-M35H)垢版2018/09/11(火) 23:40:37.34ID:XxpWxEDT0
C++コンパイラの気持ちになって考えてみなよ
お前の望みは無理だから
どうせベンチとらずに遅いとか言ってんだろ
だまってvirtual使うかダウンキャストするかそもそも継承使わないかどれかにしとけ
0030デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/11(火) 23:53:39.57ID:85ZJZj420
>>29
ベンチ取らなくても自明だろ。
そしてC流の「手動」オブジェクト指向なら、自分で関数を手動で切り替えるのだから、実現出来るんだよ。

ただ、現実的には、derived等のキーワードが出来ればC++でも普通に可能だぞ。
単一継承ではthisの値は型によらず同じだし、
この場合に親のメソッドを使ったら親の型になるというのは、
純粋に「コンパイラがエラーを検出するだけ」の為であり、実装には何ら影響がない。
だからコンパイラがエラー検出さえしなければ通るし、そのまま動作するコードになる。
C++は過剰にエラーを検出しているだけなんだよ。
0031デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/11(火) 23:57:34.93ID:85ZJZj420
なお、やっぱ継承じゃないと使いにくいわ。

A/B/Cってのはコンストラクタ/デストラクタだけの違いだから、
他から呼び出すときは型Mにして多態したいのだが、
CRTPだとこれが出来ないorz
0032デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/12(水) 00:12:26.05ID:A4EXsm7N0
必要なのは「ダウンキャストの型推論」か?

文法的に見てダウンキャストが安全な場所はあるだろ。例えば、25の
> 仮に Z : Y : X と継承していたとして、
> (Zの実体).(Xのメソッド).(Yのメソッド)
とか。
X& → Y&のダウンキャストも自動アップキャストと同様出来てもおかしくないし、これが有れば解決だ。
「ダウンキャストは悪」って事で止まってしまってるだろ。
もっとも、全部virtualで単一継承ならダウンキャストはほぼ要らないのも事実だが。
0034デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/12(水) 00:22:01.63ID:A4EXsm7N0
自己修正。

>>28
> 今のC++では最適化したオブジェクトコードを吐かせる記述が出来ない。

これは間違いだった。
いちいちダウンキャストすれば(ソースはうざくなるが)最適なオブジェクトコードが出る。
ダウンキャスト忘れはSyntaxErrorだし、妥協するならこっちかも。
0036デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/12(水) 01:44:28.46ID:A4EXsm7N0
>>35
それで何が嬉しいんだ?
記述も無駄に増えるし、何もメリット無いように思うが。
(Mへのデリゲートの部分が余分に必要)

どうせ委譲部分を全部書く気なら、
コンポジションせずに単に自前で戻り値をダウンキャストした方がいいと思うが。
例:

Class C : M {
C& from( ... ){
return (C&)((M*)this)->from( ... );
}
};

コンポジションにすると上記のアップキャスト部分(M*)が必要なくなるが、
その分無駄にポインタ一つ分データが膨らむだろ。
上記のダウンキャスト/アップキャストは実行コード上には現れないのだし、
2段呼び出しを省いてくれる最適化がかかるのなら、
呼び出し側でダウンキャストする必要が無い為、まあまあ。
(ただしfromの実体と委譲でクラス側のソースコードは増えるが)
0037デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/12(水) 02:04:07.54ID:A4EXsm7N0
ちなみに単純な実装なら
「呼び出し側でダウンキャスト必須」になってウザイのだが、
C++的にはこれが正しいような気がしてきた。
俺にはこれは「過剰な型チェック」にしか見えないが、C++はそういう言語でもある。
コンパイラのチェックから逃れる為にデータ構造を変更するのは本末転倒だし。

ダウンキャスト撲滅教の信者は、次から
・derived等、継承で親のメソッドを使ったときにも「呼び出し側の型」を返す為のキーワードの整備
・ダウンキャストの型推論
のどっちかをプッシュしておいてくれ。
0041デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/12(水) 09:10:52.74ID:A4EXsm7N0
>>38-40
そりゃ君らが老害だからだよ。

老害ってのは肉体的な年齢のことではない。
好奇心/興味を失った結果、新しい価値観を認めないから老害となる。

新しい言語を見てみろ。全てメソッドチェーン出来るだろ。
最初は戸惑うかもしれないが、慣れれば相当便利なんだよ。簡単に凝集度を上げていける。
もう1行に1個ずつ処理を書いていていい時代じゃなくなりつつあるのさ。
とはいえ、クラスも当初は無駄だと言われていたのだろうし、今ならラムダやLINQが該当するのだろうけど。
0044デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/12(水) 20:01:18.65ID:A4EXsm7N0
さて、続き。
C++で『デストラクタありの』オブジェクトを返すとき、お前らどうしてる?

α: しない。上位関数でオブジェクトポインタを渡して上書き。(Cスタイル)
β: スマポで渡す。(スマポ教)(=CLIスタイル)
γ: reinterpret_cast。 ← とりあえず今の実装
Δ: 他に何かある?

非常に当たり前だが、
戻り値として一時オブジェクトを用意すると、それのデストラクタが実行されてしまうことに気づいた。
(今更なのだが、これまではVC++/CLIでCまたはCLI(managed)スタイルで書いていて、
C++(unmanagedまたはネイティブ)スタイルはほぼ使っていなかったから気づかなかった)
これでは困ったことに、関数呼び出しで初期化がやりにくい。
具体的に、駄目なコードは以下。
0045デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/12(水) 20:02:11.37ID:A4EXsm7N0
template<typename T> struct M { // メソッド群
T* ptr;
int length;
T& operator[](int idx){return ptr[idx];}
M(int length, T* ptr) : length(length), ptr(ptr){}
M& from( ... ){ ... ; return *this;}
M& sort(){ ... ; return *this;}
// M& alloc(int length){ ... ; return *this;} // --- (α)
// M(int length) : length(length), ptr((T*)malloc(sizeof(T)*length)) {} // --- (γ)
};

template<typename T> struct C : M<T> {
C(int length) : M(length, (T*)malloc(sizeof(T)*length)) {} // heap上に確保
~C(){free(this->ptr);}
};

C<double> calc_result_vals( ... ){ // --- (γ)
calc_result( ... ); // in-placeで結果が計算される。
return (C<double>&)C<double>( ... ).from( ... ).sort(); // 結果をコピーしてソートして返す
} // <----ここでCのデストラクタが実行される

void test(int num){
MyContainer<C<double>> vals(num); // アロケーションのみ --- (β)
for (int i=0;i<num;i++) vals[i] = calc_result_vals( ... ); // 初期化 --- (α)(γ)
}
0046デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/12(水) 20:02:43.71ID:A4EXsm7N0
内容はこれまで通りだが、再度説明する。
Mはメソッド群を持つベースクラスであり、メンバ変数はポインタと長さのみ。
つまりshared_ptrと同様のヘッダであり、データは別区画にある。
Cのコンストラクタでデータエリアをheap上に確保する。
testではコンテナを用意し、各インスタンスを calc_resut_vals() によって初期化する。
Cはヘッダなのでコピーでいい。(32bit環境なら8Bytes)

というノリだったのだが、GC言語ではこれでいいが、C++では前述の通り動かない。
calc_result_vals 終了後に戻り値Cのデストラクタが実行され、データエリアが開放されてしまうからだ。
(ヘッダ自体はコピーされるが、中身が無効アドレスを指した状態になる)
このとき、お前らどうしてる?

まず思いつくのはCスタイル(α)だ。
test内の初期化を、戻り値ではなくポインタで渡し、子関数で上書きさせる。
for (int i=0;i<num;i++) calc_result_vals(&vals[i], ... ); // --- (α)
しかしやっぱ代入形式で書きたいのと、
一時オブジェクトを作らない為には、
Containerでmallocではなく各インスタンスをnewして空として初期化し、(ここまではまあいいが)
そこに上書きでポインタを初期化するというおかしな操作(allocメソッド)が必要となる。
これが流れ的にイマイチ。

スマポ教団なら全てスマポで対応しろ、か?つまりtest内のコンテナを
MyContainer<shared_ptr<C<double>>> vals(num); // --- (β)
とし、calc_result_valsはshared_ptrを返すというもの。
しかしこれは無駄にスマポを介している分ウザイし、速度も遅い。
とはいえ型には矛盾が無く、フローとしては綺麗ではある。
(GC言語は実質的に全てこれ)
0047デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/12(水) 20:04:07.13ID:A4EXsm7N0
型なんて飾りですよ、なら、MにC同様のmallocするコンストラクタを用意し、
calc_result_vals上で作る一時オブジェクトはCではなくMとし、(デストラクタが空)
代入時にキャストして強引に突っ込む、とも出来る。
M/Cの区別は「heap上に新規作成するか」ではなく、「寿命を管理するか」に変わる。
M<double> calc_result_vals( ... ){
calc_result( ... );
return M<double>( ... ).from( ... ).sort(); // Mを一時的に作り、Mを返す
} // デストラクタは空なのでheapは解放されない
for (int i=0;i<num;i++) *(M*)&vals[i] = calc_result_vals( ... ); // キャストして強引に突っ込む(γ)
代入形式で書けるし、最速コードはこれだが、強引過ぎか?
ただC++でこれやったら最適化によっては死んだような…

お前らどうしてるよ?
他の方法(Δ)が有れば是非。
なお、「Cを継承したDを作り、Dのコンストラクタ内でcalc_result_valsを呼んで初期化」は
無意味に結合が増えそうなので却下。
0048デフォルトの名無しさん (ワッチョイ 13f2-7GfT)垢版2018/09/12(水) 20:18:03.00ID:OXipbDDC0
>>41
関数型言語で使われるパイプラインとの区別もついてないんだろうねぇ。
mutableなオブジェクトに対して連続的に操作を行う際にレシーバの記述を
省略できるというだけでしかないのに。
0049デフォルトの名無しさん (ワッチョイ db4f-f65Y)垢版2018/09/12(水) 20:40:38.92ID:A4EXsm7N0
>>48
意味不明。そもそも俺は「パイプライン」知らんし。

以下見る限り、データをメソッドで処理するのではなく、
データをメソッド配列(メソッド関数ポインタ配列)にくぐらせる感じか?
> https://postd.cc/an-introduction-to-functional-programming/
しかし今回は演算結果をコピーしてソートして返すだけだから、どっちでも変わらん気もするが。
callが使えればパイプラインも生きるのかもしれんが。
0054デフォルトの名無しさん (ワッチョイ 57b3-IhZi)垢版2018/09/13(木) 10:15:51.60ID:d4HLHzfO0
class C : public Mのときに
c.chain().chain.chain()で戻り値がCの型のオブジェクト指向の静的型付き言語を知らないんだけどあるの?
少なくともc++、c#、java、kotlin、swiftはできない
0056デフォルトの名無しさん (ワッチョイ 174f-9b2l)垢版2018/09/14(金) 00:03:28.50ID:XcO59d500
一応報告。
色々調べた結果、placement new を使えばαの時の「未初期化のthisを使う」気持ち悪さは無くなることが分かった。
これとムーブを比べると、以下。

Cスタイル(α):
× 代入形式で書けない。
◎ 最初から最速コードが出る。(costructのみ)

ムーブ:(俺の環境では)
◎ 代入形式で書ける。
△ダウンキャストを書く必要がある。
× return (C<double>&)C<double>( ... ).from( ... ).sort();だと全く最適化されず、
 construct/copy/destruct/move/destructとなる。
△ C<double> retval(pat->num); retval.from((double*)pat->result).sort(); return retval; とベタに切ると、
 NRVOが一つだけかかり、construct/move/destruct となる。
(opereator=のオーバーロードが最適化に影響しているかも試したが、関係なかった)

いまいちソースは美しくないが、速ければいいだけならCなのはいつも通り。
(NRVOの最適化済みソースを手動で書くのだから当然)
ムーブにするか、いっそのこと代入/コピー禁止でunique_ptrの機能も持たせるか考え中。
0057デフォルトの名無しさん (ワッチョイ 174f-9b2l)垢版2018/09/18(火) 22:37:48.65ID:9yuSYzSe0
コンテナを自作しようとしているのだが、デストラクタの書き方が分からない。
教えてもらえないだろうか。


(自信は持てないが)
俺の理解では、コンテナのデストラクタは中身のデストラクタをキックする必要があって、
今は以下のように書いていて、それなりに動いているように見える。

~MyContainer(){
for (int i=0;i<length;i++) ptr[i].~T();
}

要するに中身のデストラクタを一つずつ直接呼び出している。
ところが、例えばGNUのvectorのデストラクタは空だ。

> 00126 ~vector() { }
> https://gcc.gnu.org/onlinedocs/gcc-4.6.3/libstdc++/api/a01115_source.html

これはどういう事なのだろうか?
他に参考になるソースでもいいから教えてもらえれば助かる。
なお、以下では俺と似たようなことをやっている。

> ~Stack () throw()
> {
> std::for_each(array_, array_ + top_, destroy<T>);
> ::operator delete(array_); // グローバルスコープの delete 演算子
> }
> https://ja.wikibooks.org/wiki/More_C%2B%2B_Idioms/%E6%B1%8E%E7%94%A8%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E4%BD%9C%E6%88%90%E7%94%A8%E3%82%A4%E3%83%87%E3%82%A3%E3%82%AA%E3%83%A0(Generic_Container_Idioms)
0059デフォルトの名無しさん (ワッチョイ 174f-9b2l)垢版2018/09/18(火) 23:09:28.88ID:9yuSYzSe0
>>58
なるほど。
ではそのアロケータのdeallocateメンバ関数は誰がキックするんだ?
俺はそれが vector のデストラクタに書かれているのかと思っていたんだが。
以下参考。

> C++11では、std::allocator_traitsというアロケータアクセスの中間インタフェースが用意されたおかげで、
> 自作アロケータに必要な実装がだいぶ減りました。
>
> 自作アロケータに必要な最小コードは、以下のようになります。
>
> 要素型value_type
> 特殊関数(デフォルトコンストラクタ、コピーコンストラクタ、ムーブコンストラクタ)
> 別な要素型のアロケータを受け取るコンストラクタ
> allocate()メンバ関数。(hintパラメータはあってもなくてもいい)
> deallocate()メンバ関数
> operator==とoperator!=
> https://faithandbrave.hateblo.jp/entry/2014/02/14/160506
0061デフォルトの名無しさん (ワッチョイ 174f-9b2l)垢版2018/09/18(火) 23:34:08.49ID:9yuSYzSe0
>>60
vector内部にallocatorを持っている場合、
allocatorのデストラクタはvectorのデストラクタが呼び出してやらないと連鎖しなくね?

なお、以下ではやはり自分のデストラクタででfreeを呼び出し、その中でalloc.deallocateされてる。
> StrVec::~StrVec() { free(); }
> https://books.google.co.jp/books?id=P1D5DAAAQBAJ&;pg=PT746&lpg=PT746&dq=deallocate+%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%97&source=bl&ots=1rmEQsOAY0&sig=
NRKyLHuLVtPQK5Yb2Nk_YU_pTNs&hl=en&sa=X&ved=2ahUKEwjCwe_q3sTdAhUNQd4KHc2FDi0Q6AEwA3oECAcQAQ#v=onepage&q=deallocate%20%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%97&f=false
0062デフォルトの名無しさん (ワッチョイ 9780-9b2l)垢版2018/09/18(火) 23:39:15.31ID:oE0uJFU60
いろいろと間違ってる

> for (int i=0;i<length;i++) ptr[i].~T();
> 要するに中身のデストラクタを一つずつ直接呼び出している。

こんなことする必要ない
デストラクタはインスタンスが消滅するまえに自動的に呼ばれる

↓コレはdebug用 みるソースが適切じゃない
> https://gcc.gnu.org/onlinedocs/gcc-4.6.3/libstdc++/api/a01115_source.html

00078 #ifdef _GLIBCXX_DEBUG
00079 # include <debug/vector> ← コレをみてる
00080 #endif


↓こっちみなさい
https://gcc.gnu.org/onlinedocs/libstdc%2B%2B/libstdc%2B%2B-html-USERS-3.4/stl__vector_8h-source.html
00268 ~vector()
00269 { std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish); }
0063デフォルトの名無しさん (ワッチョイ 174f-9b2l)垢版2018/09/18(火) 23:48:11.97ID:9yuSYzSe0
>>62
おおサンクス。見るソースを間違えていたか。

なお俺が作ろうとしているのは「コンテナ」な。
だからデストラクタの連鎖の開始をキックする必要がある。
そのソースでもされてるだろ。
0064デフォルトの名無しさん (ワッチョイ 174f-9b2l)垢版2018/09/18(火) 23:49:51.14ID:9yuSYzSe0
× デストラクタの連鎖の開始をキック
○ デストラクタの連鎖をキープ

開始のキックはコンパイラによってされるが、連鎖は手動でキープしてやらないと次に続かない。
コンテナの場合はこれが必要なはず。
0066デフォルトの名無しさん (ワッチョイ 174f-9b2l)垢版2018/09/19(水) 12:58:39.27ID:GJOADTEF0
>>65
ああ、目の付け所はそこで合ってる。
先に言っておこうかとも思ったが、話が無駄にずれるので止めておいた。

わざわざコンテナを作ったのは、コンテナ領域をallocaで確保したかったから。
そこに結果的に placement new して、ヒープ領域にデータ領域を持ったオブジェクトを配置してる。
だからそれらを解放してくれないと不味い。
そのデストラクタをコンテナのデストラクタからキックしている。
(というか、これをやらせる為に簡易コンテナにした。
単にallocaで可変長配列を確保してその中に入れただけでは、
デストラクタを起動するコードが『自前で、上位側に』必要であり、これがC++の思想と反するから)

要するに alloca をもっと使ってみようというテストなのだが、
「コンストラクタで領域を確保出来ない」(関数呼び出しでは初期化出来ない)のが地味に使えない。
C++は何故か forceinline までも「無視していい」という仕様にしているようだし。
(inlineは無視してもよく、forceinlineは無視しては駄目、という仕様に普通はするだろ)

ただ、自作アロケータを既存のコンテナにはめ込めるのなら、その方がいい。
この解があるなら alloca がいらない子扱いなのも道理だ。
0069デフォルトの名無しさん (ワッチョイ 174f-9b2l)垢版2018/09/19(水) 18:54:14.05ID:GJOADTEF0
>>67
駄目だな。
仮想関数にしないといけないのと、
それは子が子のままでいられるだけであって、子が親のメソッドを使った後も子で居続けられるわけでない。

> 実際に取得する型が親クラスに引っ張られないメリットを享受できる
> 自分自身の型を返す関数を定義する時など、親クラス固定だと、受け取った側でのキャストが面倒ですしね。
> http://cpp.aquariuscode.com/covariant-type
やはり既知の問題ではないか。

(C++しか使ったことがないなら意味が分からないと思うが)
JavaScriptの場合はクラス階層とインスタンス階層が分離しており、
各インスタンスはクラス階層を派生させてを作る。
だから元々親階層のメソッドから子階層のメンバ変数を参照出来るし、それがデフォの使い方だ。

クラス階層とインスタンス階層は文法的には違いが無く、クラスも継承出来るが、インスタンスも継承出来る。
これを上手く使えば、メモリを大幅に節約することが出来る。
C++にはこの記述能力がない。
理由はクラスとインスタンスが明確に分離しているからだ。

JavaScriptの挙動をC++用語で言えば、
thisが常に仮想thisであり、メンバ変数は全部仮想メンバ変数となっている。
だから親のメソッドを使っても派生型のままであり続け、自由にメソッドチェーンが出来る。

ただしここら辺はやや宗教的でもある。
親クラスの関数が派生クラスの変数を操作することを「仮想this」で実現するなら、
型安全ではなくなってしまう。
ただし実装は、単一継承の時には単に型チェックを外すだけと、極めて簡単であり、やる気だけの問題だ。
(ただしC++の場合には多重継承があるので若干問題がある)
なお、型安全を取りたいなら、仮想thisではなく、仮想メンバ変数で実現する事になる。
こちらはC++でも問題はない。(ただし動作速度が遅くなるが)
0070デフォルトの名無しさん (ワッチョイ 174f-9b2l)垢版2018/09/19(水) 19:13:17.80ID:GJOADTEF0
>>68
当初は delete &ptr[i]; と記述していたのだが、これは
1. ptr[i].~T(); (各エレメントのデストラクタのキック)
2. free(ptr[i]); (メモリ区画の解放)
の2つを実行するらしくて、駄目だった。
今の各エレメントはallocaで確保した区画に placement new しているので。

> 不思議なもん作ってんのなw
今回は事前に全部計算してalloca出来るが、
コンテナ長だけ親で確定、中身の長さは子でしか確定出来ないことも普通にあるだろ。

例えば、LGBT共のおかげでFacebookには56種類の性別があるらしいが、
これに対して、無作為に10,000人の性別を調査するとして、
コンテナ長は56で親で決まるが、
各性別人リスト長は子関数で調査しないと決まらないだろ。そこをheapに取ってる。
勿論、親も含めてheapに取り、ジャグvectorとするのがC++流であり、だからC比でいちいち遅くなる。
そこら辺を改善出来ないかのテストだ。
0072デフォルトの名無しさん (ブーイモ MMbf-nprU)垢版2018/09/19(水) 22:41:00.05ID:x2iiusAWM
>>70
何を悩んでんのかよくわからんが
普通にヒープから取ったんならdeleteだし
スタックをplacement newしたんなら自分でデストラクタ
それだけの話
というかね、はっきり言ってでかいデータをスタックに置く発想がセンスないぞ
0073デフォルトの名無しさん (ワッチョイ 9780-9b2l)垢版2018/09/19(水) 22:56:01.63ID:xLP4ypV20
アホやな
スタック関係ない

アホは連続した一枚の板みたいなヒープに
ポインタの列ではなくオブジェクトインスタンスのメモリイメージの列をシリアルに並べてる

ホントな、アホしかいいないわ
0075デフォルトの名無しさん (ワッチョイ 9780-9b2l)垢版2018/09/19(水) 23:10:27.91ID:xLP4ypV20
たとえば64byteのメモリが必要なクラスがあったとする
アホが作ったコンテナでは例えば要素が5個なら
こんな感じになるとアホはいってるワケ

 [0][64byte]
 [1][64byte]
 [2][64byte]
 [3][64byte]
 [4][64byte]

メモリの板に64*5のメモリイメージが配置される
要素が1つ増えるたびに64byte必要になることになる

ポインタなら(仮に32bitなら)こうなる

 [0][4byte] ← [64byte]
 [1][4byte] ← [64byte]
 [2][4byte] ← [64byte]
 [3][4byte] ← [64byte]
 [4][4byte] ← [64byte]

メモリの板に4*5のメモリイメージが配置される
さらに64byteのバラバラのメモリが5個できる
つまりメモリフラグメンテーションがおきることになる
0077デフォルトの名無しさん (ワッチョイ 9780-9b2l)垢版2018/09/19(水) 23:17:16.10ID:xLP4ypV20
そもそもスタックとかいってるオマエも
相当頭悪いという自覚が必要
0079デフォルトの名無しさん (ワッチョイ 9780-9b2l)垢版2018/09/19(水) 23:28:50.52ID:xLP4ypV20
さよか
0080デフォルトの名無しさん (ワッチョイ 174f-9b2l)垢版2018/09/19(水) 23:50:52.77ID:GJOADTEF0
>>71
お前が、というより最近の奴が何故
「俺の知ってる言語の『優位性』」に固執するのか甚だ疑問ではある。
ただ、お前は>>37も理解出来てないのだから、まずは「オブジェクト指向」を理解した方がいいぞ。

>>74
JavaScripterはそれ以前で、オブジェクト指向そのものを知らない奴が多いし、
他言語から来た奴は無理に「クラスベース」として捉えようとして誤解し、
しかもそれを垂れ流して間違いを再生産し、どうしようもない状況になってる。
JavaScripterには馬鹿しかいない。これは断言出来る。

>>76
俺はもう動けばいいだけなら普通に作れるんだよ。
その上で、C++の動作速度が遅く、記述がかったるいのを何とかしようと試してる。
先に言っておくが、俺はC比同速程度を目指している。
スマポ(キリッなC++なんてJavaよりちょっと速い程度しか出ないし、それなら俺はCLIを使うからそれでいい。
ただしC流の書き方は見た目分かりにくいから、
C比で遅くならない、或いは多少程度でもうちょっとましに書けないか試している。

今回のにしたって、最速はC流の「頭で全部分確保、ポインタで細切れにして渡す」に決まっている。
ただこれは見た目何をやっているのか分かりにくいし、関数に分割もしづらい。
クラスにしたって、仮想関数なしなら速度もメモリもオーバーヘッドはない。なら使わない手はない。
そういう、C比オーバーヘッド無し(或いは僅か)程度で、どこまで分かりやすい見た目になるかを試してる。

楽に書きたいだけなら、JavaScriptが現状最強だ。
C比5倍程度であの楽さ、他の言語なんてやってられない。
速ければいいだけならCだ。ただし記述が見た目分かりにくいのは否めない。
それでC++でどこまでCを改善出来るかを試している。メソッドチェーンもそれの一環だ。
0081デフォルトの名無しさん (ワッチョイ c980-yqSl)垢版2018/09/20(木) 00:06:31.99ID:zLqp8E230
だったらふつうにPODの配列でいいわけだからな
0082デフォルトの名無しさん (ワッチョイ c980-yqSl)垢版2018/09/20(木) 00:08:31.80ID:zLqp8E230
Cでわかりにくいコードを書くには
頭悪いという才能がいる
008471=67 (ワッチョイ 01b3-coYL)垢版2018/09/20(木) 00:27:41.21ID:CPfoYuVJ0
>>80
携帯とPCで書いたから同一人物とわからんかったかな
何か実現したいことがあって
>・derived等、継承で親のメソッドを使ったときにも「呼び出し側の型」を返す為のキーワードの整備
と書いてたんだと思って、解決策になるかもしれない情報を教えてあげようと思ったら
感謝もせんとC++に対するヘイトを垂れ流すだけだったから「ああ、あいつか・・・」となったんだが

>「俺の知ってる言語の『優位性』」に固執する
どこをどう読んだらそうなるのかわからん。というか鏡見ろ
0085デフォルトの名無しさん (ワッチョイ c980-yqSl)垢版2018/09/20(木) 00:31:01.70ID:zLqp8E230
遅いのはオマエのウンココードのアルゴリズムのせいだからな
気にする必要ないほどのオーバーヘッドが問題じゃない
0086デフォルトの名無しさん (ワッチョイ f94f-yqSl)垢版2018/09/20(木) 00:50:45.72ID:Yonx2vGH0
>>72
> スタックをplacement newしたんなら自分でデストラクタ
自分でデストラクタを書かなくて済むようにコンテナを用意してるんだよ。

というか、そもそもC++の思想はそうではないか?
ある意味、クラス外のコードでデストラクタを書いたら負けだろ。
そしてコンテナを用意するだけでこれを回避出来る。
それだけの話だ。

「書けばいい」の発想もいいが、俺はもうそれは十分出来るので、
書かなくて済む物を如何に増やすか、それを試してる。
結局、スクリプト言語が楽なのはここだし。


>>83
もう動作はしてるし、結果も比較して問題ないのを確認済み。
まあ、 alloca は相当使いづらいことも分かった。


>>84
いや、ワッチョイが同一だから同一人物だと認識してる。

> 解決策になるかもしれない情報を教えてあげようと思ったら
解決策になってないし、お前はそれが間違いだとも認識出来てない。
お前の情報は何の役にも立ってない。

馬鹿が間違ったことを言ってきて「間違ってるぞ」と言ったら「それでも感謝しろ」と言われた状況だ。
そういう考え方もありだが、俺はここではそれをしないし、する必要も無いし、するべきでもないと思ってる。
ここでは、間違ったことを言った奴は叩かれるべきだ。
そうでないと馬鹿がどんどん寄ってきて、結果、レベルが下がり、誰にとっても利益が無くなる。
間違ったことを言っても感謝されたいなら、少なくともIDやコテハンが付いてる場所へ行け。
そういうところが好きなら、そういう場所を盛り上げるべきであって、ここで文句を言うべきではない。
0089デフォルトの名無しさん (ワッチョイ 82d8-jhFb)垢版2018/09/20(木) 04:25:13.14ID:gyMuKR+I0
IntelのC++ Composerってサポート期限切れのシリアルでも使用可能なバージョンがあるのね
知らなかったよ

2017 update7
>This update can be installed even if your support service has expired using your existing Serial Number.
0090デフォルトの名無しさん (ワッチョイ 42a1-UYTc)垢版2018/09/20(木) 22:36:33.27ID:sE8+iEgQ0
はじめまして
ゼミの課題でc++でバカラのプログラムかいてこいって言われたんですけど
簡単ですか?
0092デフォルトの名無しさん (ワッチョイ c980-yqSl)垢版2018/09/20(木) 22:41:55.13ID:zLqp8E230
まずサイコロの運動をシミュレーションするところから
0094デフォルトの名無しさん (ワッチョイ c980-yqSl)垢版2018/09/20(木) 22:48:19.01ID:zLqp8E230
待ち行列で客が待つのもポアソン分布使ってシミュレーションする必要がある
0098デフォルトの名無しさん (ワッチョイ df7b-Z3mi)垢版2019/02/04(月) 15:45:55.20ID:01AVniBC0
「64bitのコードでコンパイルするよう指定」するやつだっけ?

「デカいメモリ」「エラーコード〜でブルースクリーン」ていう
キーワードで、記憶に引っかかる感じ。
■ このスレッドは過去ログ倉庫に格納されています

ニューススポーツなんでも実況