C++相談室 part132
レス数が1000を超えています。これ以上書き込みはできません。
次スレを立てる時は本文の1行目に以下を追加して下さい
!extend:on:vvvvv:1000:512
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。
前スレ
C++相談室 part131
http://mevius.2ch.net/test/read.cgi/tech/1501295308/
このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.101【環境依存OK】
http://mevius.2ch.net/test/read.cgi/tech/1500329247/
■長いソースを貼るときはここへ。■
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 散々スレ散らかしておいて挙句誰もスレ立てないとか何なんだよおい swap(T& x, T& y) { T tmp = x; x = y; y = tmp; }を
swap(T&&x, T&& y) { T&& tmp = x; x = y; y = tmp; }とかやったら死ぬ気しかしない 2 名前:デフォルトの名無しさん (ワッチョイ bf54-lR6P)[sage] 投稿日:2017/03/31(金) 16:52:18.52 ID:CoeIAoH10
STLつかうと一気に実行ファイルサイズが10倍に?!
環境によるだろ。
俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力
ランタイムを使用するようにして使っているが、例えばstd::vectorを
使っても使わない時と比べ10Kほどしか増えない
すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。
C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。
とかいうエラーが出るんだけどこれってどうすればいいの?
#include <stdafx.h>
後死ね。
言葉が悪いな。それで教えているつもりか。
まぁヒントぐらいにはなったな。
うむごくろう。
---- テンプレ ここまで ---- テンプレに
>>970が建ててね
辺りを追加しとこうぜ 開発的なお話で単純に構造体の要素を一つ追加するって危険な行為でしょうか? 質問がふわふわし過ぎ
そんなんじゃまともな回答は無理
個人的には
メンバをひとつ追加する程度で
破綻のリスクが増えるというなら
それは元々破綻していて
表面化していないだけだろうと思うが >>10
ふわふわしすぎてました
意味合いとしては答えてくれてることで合致してます
メンバ変数を一つ追加することでその他への影響は大きいでしょうか?って意味でした >>11
メンバー変数を増やすと、構造体のサイズが増大する。また、変数の追加する場所によっては、メンバーの相対的な位置が変化する可能性がある。
よって、その構造体のバイナリーインターフェースに依存するプログラムは死亡する可能性がある。 例えば、構造体データをバイナリーとしてファイルに出力していたら、サイズの増えた構造体では正しく読み取れない可能性がある。
構造体のメンバーの相対的位置が変化したら、古い構造体を使っている他のプログラムとは相性が悪くなる。 Windows APIでは、構造体をバージョン管理して、構造体のサイズで処理を変えたりしている。 >>14
たまに半端な位置に「予約」とか説明されてるメンバがあったりするよね。
あれはバイナリサイズが変わると困るような理由があるからなんかなぁ。
まあ、たいした理由もなくやっちゃって互換性ゆえに変えられなくなったとかだろうけど。 >>15
位置やサイズが違うとバグのもと。
昔はよく
#include <pshpack1.h>
...
#include <poppack.h>
を書いたものだ。 cURLを限りなくスペックの低い組み込み機器に入れようとしてるところで問題が起きました
・処理能力が低い
cURLをsystem関数でコマンドライン実行しようとすると、
呼び出す側の処理がCPU50%平均的に食っている+cURLもCPU喰うでまともに通信が出来ません
呼び出す側を落とすとcURLの処理速度は改善されるから
確定でCPUの食い合いが原因ってのもわかっている
対策として下記二つが出たのだけど
・呼び出す側をcURLが実行中はsleepにする
・cURLを実行ファイルで取り込むのではなくプログラミングベースで取り込む
上は常に通信をしているためにsleepを挟むことはできず
下のプログラミングベースについてもクロスコンパイルの問題でなぜか上手く行かない
これ以外の方法で対処方法ってありますか? >>18
なぜかうまくいかないときのエラーメッセージは何だ? スペックが低いなら、そもそもマルチスレッドが未実装の可能性がある。
ならばsleepは無意味ということになるかも知れない。 スペックが低すぎると、ANSI Cなどの規格に準拠してない恐れがある。
マシンとコンパイラーのマニュアルを確認して、準拠状況を確認しろ。 >>18
状況がよくわからんなぁ。
system 関数自体は普通は同期的だよね?
スレッドを分けて system 関数を実行した上で、
メインプロセスと cURL がプロセス間通信 してるってことかな。
(すまん、ミスって変なところで投稿してしもうた) この件に関しては >>19 の疑問が当然だなぁ。
クロスビルドでこの手の問題がありがちなのは、
ライブラリのサーチパスとかかな。
ライブラリが見つからんとかメッセージ出てないかね? >>19
undefined 系統のエラーが沢山出る
arm-linux-gnueabi-gccを使ってコンパイルするとそうなる
ただgccだとエラーは起きない。ただi386系になるから実行環境で動かない
クロスコンパイルでcURLの単体がARMにできているから
.aファイルもARM担っていると思っているのだけどもなっていないのだろうか
objdump実行でARMって文字を確認したからARMだと思いたいとこではあるが…
エラー時の実行例
arm-linux-gnueabi-gcc test.c -o test.out -LXXXXXX -lcurl
通るけどi386系で実行環境で実行できない
gcc test.c -o test.out -LXXXXXX -lcurl
>>22
今の状況はPCA-PCBと通信がしたい。着目しているのはPCA
PCAがPCBと通信をする独自規格を元々持っていたのだけど、そのPCAが持っている独自規格を色々な規格をサポートしているcURLに置き換えるって話
今まではPCAの中のメインプロセス(CPUを一番食っているやつ)が通信を行っていただけだったから特に問題は発生しなかったけども
今回はメインプロセスがcURLをコマンドライン実行で呼び出す設計にしようとしている
そのためメインプロセスと別のcURLというプロセスが起動することになると考えている
なので、実装前にメインプロセスが生きている状態で直接コマンドプロンプトでcURLを実行し、動作検証したら通信自体はできるけど動作がとても遅いってとこ露に行きついた
調べてみると、メインプロセス・cURLともにCPUを食いあって速度が遅くなっていることも確認できて
どうやったら上手く実装できるだろうか…と悩んでいるところです
sleepに関しては実装して確認したわけではないけど、kill -stop PIDで実行したら
上手く行ったからsleepも上手く組み込めば対応できrのではないかと思ってる
>>25
forkでこれ以上増えるとさらに遅くなると思ってる… メンバ変数が1個増えたぐらいで崩壊するのは
対外的にはカプセル化がうまくいっていない例、
内部的にはクラスのふるまいに激甚な影響を与えるような重大なメンバ変数の追加が
後から必要になるというのはマズーな設計の例、 フォークは低速な外部記憶からプログラムコードを新たにロードする手間が無い分高速な可能性が微レ存、
フォーク先とフォーク元でコードが共有されるためメモリ使用効率も多少UP、
あとサーバとクライアントの関係にある処理を(無理矢理)1本のプログラムとして書けるので
開発環境のリソース自体厳しく制限されていた昔はややうれしかったのかも知れん、、 ていうか根本的な疑問として
CPUが低速であるとわかっていながら応答速度の要求があるタスクの一環に
プロセスの起動を含めるのってどうなんじゃ…
(プロセスやスレッドの起動は低廉なOSでは一般にリアルタイム性が全く最強度で担保されない
応答速度の要求が見積もれていなかったんだとすると極めてご愁傷様な話… %%%%4NEL%%%%
000-SAV-&1.0888214%ML<\47MBL%0.2\MSSSS4.213>
1.8882/%B/%SB/<\2/7BL\%\%B!B%47L%Si72B>%10.2%\
002%\B%===>>>52.B<\rbc/2.8>>\7B<<\7LB>>\72S\<%\42%><\br>001BYON$\%7L2%3.33GHz>>>2.3GHz<\br>
41.B%LB%"<<%11.6$%><<\86.1B>>2LB>"B???S3>>71$-?>6%<\br>
082@<\7L@@<\br>
\LOOP>0<1Entra つかだいたいやるべきこと:
1. プログラムを全般的に速くする
2. (今から可能ならば)要求元とハンドシェークして必要なだけ待ってもらうしくみにする
3. 間に合わせたい処理の優先度を間に合っている処理より上げる
(できればワーストケースでの応答時間の上限を担保する
>>20
sleepしてもスレッドコンテキストが切り替わらないOSというのはさすがに都市伝説なんじゃ… 訂正
×: プログラムを全般的に速くする
●: プログラムのボトルネック箇所を探して速くする
この場合プロセスの起動がボトルネックなのはまちがいなさげなのでそこを速くなるように修正汁、 cURLでググったらlibcurlってのがある。こっち使えばすべて解決する話じゃないの。
そもそもC++スレなのにlib使わずコマンド経由する理由が謎。 ウンコの画像を生成するプログラムの作り方を教えて下さい MMD、Blender、メタセコイアなど好きなヤツを使ってオブジェクトを三次元モデリングしろ。
ボーンを設定して、思ったとおりに変形できるようにしろ。
レンダリングして、画像として保存しろ。 線を引いて多様なウンコ画像を生成するプログラムお願いします! 基本オブジェクトをいくつか作れ。
基本オブジェクトを変形し、組み合わせれば、求める画像がレンダリングできる。
重力とボーンを考慮すれば自然な形になる。 AIがウンコ画像を識別できるなら、逆にウンコ画像を生成することもできるのではないか?
これを応用するとエロ画像を識別できるAIにエロ画像を生成させることもできるのでは? まずは、MMD、Blender、メタセコイアのどれかを選んでダウンロード&インストールしろ。 >ボーンを設定して、思ったとおりに変形
要らんだろ・・・・w
アラレちゃんにつんつんでもさせるのかよ cURLの起動云々の話に答えてくれた人ありがとう
応答速度についてはめちゃくちゃ遅いってレベルにならなければ問題なく
プロセスを立ち上げるような処理を入れても問題ないとの判断
極端な話10秒で終わっていたのが20秒になりましたぐらいなら問題なく、これが600秒かかりますとかなら問題あった
実際にプロセスを立ち上げてみて処理させてみたけど
CPUの食い合いがなければこの問題は解決できていると考えている
処理についてsleep入れるのは無理そうってレスしたけども
ソースコードを追ってみたらpollなどではなくwhile&usleepでの待機が存在していて
CPU喰ってたからこいつをちゃんと制御すれば問題なさそうってなりました
考えてくれた人ありがとう
別案件なんだけど何か良い実装方法がないか相談させてほしい >while&usleep
時間の掛かる、I/O で、busy wait する奴って、素人だろ 1. PCA→PCBへのインストールで新規にcURLの実行形式ファイルを入れることになった
2. インストールが完了して再起動をしたら今後はcURLをsystem関数で実行して通信する
この状況下でダウングレードを試みようと考えた時に
3. PCA→PCBへのダウングレード(インストール)をcURLを用いてする
4. インストールが完了して再起動をしたら今後は独自プロトコルでの通信に戻る
こういう状況になった。
その時に、cURLを削除するタイミングが見付からなくて今困っている。
3を実行したときに判断しようとしたのだけどダウングレードだと判断するに至る材料がない。
ファイルを一個ずつ指定して送信して・・・の繰り返しだからリストにcURLがあるかないかも判断できずってなっている 書いてて気づいたけどこれC++の話じゃないって
もうスレチだと気づいたので無視してください
スレ汚しすまん >>48
なるほろ
優先度の低いスレッドのビジーループは必ずしも悪ではないと思っていたが
低速なI/O命令を含むビジーループだと応答性能のドブ捨て度が増すのか、 usleepしてるんなら優先度関係ないだろ
誰だ変なこと言ってるのは ネット回線なんか、秒の単位だから、busy wait の範囲を超えてる
busy wait は、せいぜい、1ms 以下とか、
マイコン・リアルタイムOS での話 もしかしてusleepがビジーウエイトで実装されているとでも思っているのか CPU 使用率が、100% になってたんじゃないのか? >>52
あるわ;
優先度が高いスレッドにビジーループされるとそいつがsleepしてくれる間隔が
全スレッドの応答時間の下限になってしまう
優先度が低いスレッドのビジーループならsleepを待たずに割り込めるからそこまで甚大にならない
ただしI/O命令があってそいつが数百マイクロ棒かかると
より高いスレッドであってもワーストケースの応答時間が数百マイクロ棒に劣化する usleepは普通電気が無駄なのでhaltでもしてハードウェアに割り込みを待たせるが
マルチコア対応OSやったら気分次第でスピンロックでビージループすることもあるかも試練、 スマン
>usleepは普通電気が無駄なのでhaltでもして
というのは他に実行権待ちのスレッドが無かった場合の話ェ、 OS は、たぶん優先度を上下させるから、要注意。
優先度の低いスレッドでも、カーネルモードに入ると、優先度を上げるのじゃ?
優先度の低いスレッドのカーネルモードが、
優先度の高いスレッドのユーザーモードよりも、優先されるかも?
ただ、CPU 使用率が、100% と表示されていても、
本当は、CPUを使っていない場合もあるとか、聞いた事もある >>56
おまえさん、やっぱり前提がおかしいな
> 優先度が高いスレッドにビジーループされると
そんな話してねえぞ
usleepしてるんならと言ったろ
なんでビジーループが出てくるんだよ ftpサーバを立てられないからプログラミングまで進まない悲しい
530エラーってなんでえええ
IIS使いにくい 俺もIISでFTPSサーバ立てられなくて困ってるわ
IIS思った以上に使いにくい
IISでオレオレ証明書を作成して
FTPS通信をcURLで確立したいだけなのに
本当にできるのだろうか >>63,64
まあそういう話は適切なスレに行ってしてくるといいぞ セキュリティソフトやファイアウォールが通信の邪魔をしている場合があるから、気を付けな。 なんか難しい設定あったかな
SFTPできないならありそうだが >>66
そういう実験はまずVMでやれ、だよな
完全に無防備なら本来どうなっていたという話からクリアして
セキュリティの入った環境で引っかかった場合に切り分けをしながら、と usleepの実装ってどんな感じ? どれくらいのμ秒の精度出んの?
ループ中に頻繁に読んでいいものなのか? 色々あるでしょ。
CPUが時計対応ならそっち見るだろうし、最悪ビジーループ。
不安ならchronoで寝るとかもあるぞ。 ググると最低4msとか出てくるな。MSみたいに最初からミリ秒単位にしとけば変な誤用されないものを。 ガベージコレクションがないのに、安全なオブジェクト指向プログラミングなんてできるんですか? ガーベージコレクションも含めて実装するのが真のC++グラマーやでアマチャン >>73
RAIIを徹底するのがC++流リソース管理法
いつ走るかわからないGCなんかよりずっとcontrollable GC要求が発生する前にプロセスが完了すりゃいいだけだろ スレッド間の変数の共有って
・pthread時に引数与える
・シングルトン
・グローバル変数
これ以外に何かあるかな? C++を最近学び始めた者なんですが
ファイルへの保存で質問があるんですが良いでしょうか
テキストに保存するのと、バイナリに保存するので
文字列を保存するとバイナリが僅かに小さくなるんですが
vectorを保存すると逆にバイナリのほうがサイズが大きくなるのは
普通のことなんでしょうか? vectorの二次元配列を、forの二重ループで
テキストへは outputfile << data[i][j] << "\t";
バイナリへは outputfile.write((const char*)&data[i][j], sizeof(data[i][j]));
で書き込んでみてるのですが・・・・・・
100×100の配列を書き込むと
テキストが29キロバイト、バイナリが40キロバイトに
配列を大きくすればするほどバイナリが大きくなってしまいます >>84
同一アドレス空間である以上、アドレスさえ取れればどんな方法でも共有できると思うよ。 >>86
どんなデータかによる。intを保存しようとしててデータが全部一桁ならバイナリの方が大きくなることもあるかもしれない。
まずキャストの使い方が間違ってるので、さっくり消してみよう。
次に読み取り部分を作って正常に読み取れるか見てみよう。 >>85
dataの型が解ればもう少し推測できるけど
char data[100][100][MAX_STR_LEN];
だとして
data[0][0] = "data\0qwe"; // "qwe"はゴミ
みたいにnull terminated後の不要なゴミも書き込んでるんじゃない?
バイナリエディタでバイナリファイル覗いてみれば解るかと
サイズから推測するとMAX_STR_LENは4かな あ、ofstreamのwriteって引数const char*なのか
ゴメン間違ってるってほどじゃないわ
せいぜいC++っぽくreinterpret_castに変えるくらいか >>91
いや、私の誤りでした、だろ
何が間違ってるほどじゃないだ
日本語間違えるなよ
>>86
出力したテキストファイルの中身は?何か差分は無いの?
少ない情報出してここで聞くより
見た方がよっぽどわかるだろ レス有難うございます。dataはintのvector二次元配列で
int a=100;
int b=100;
vector< vector<int> > data(a, vector<int>(b));
このdataに、forで
data[i][j] = rand() % 100;
の数字をいれている配列なんです
バイナリ保存したデータを、FavBinEditというものでみてみると
数字と数字のあいだに間隔があいてるので
これがサイズが大きくなってる理由なのかと思うんですが >>93
int型の100*100配列なら約40K byteなんだから、バイナリファイルは正しいと思うよ。
で、テキストも間違っているとは言いきれない。
例えば一桁の数字が多いなら、バイナリファイルより小さくなるよね?
サイズの違いはあって当然だと思うけど。 そういうものなのですか
ネット上に、バイナリに保存するとサイズが小さくなる
という話が多いのでそう思い込んでました
自分には関係無いような、複雑なデータを扱うと小さくなるのかな そういうもんですね 自分もintなら納得です
「rand() % 100」なら文字列にしたとき"0"(=0x30)から"99"(=0x3939)と2byteで収まり
"\t"を付けても 常に4byte(=sizeof(int) システム依存)より小さいですから
バイナリだと0を0x00000000, 99を0x63000000(リトルエンディアン)で保存してます
試しに「rand() % 100」を「10000」とか
"文字列にしたとき'\t'も含めて4文字を越える大きさ"にすれば
サイズが逆転するのが観察できるはずです
・扱う数字が小さいからテキストの方が短くて済んでる
・バイナリなら数字が大きく(当然intの最大値を越えないこと)なってもサイズが一定で済む
余談ながら
バイナリで保存するならバイトオーダー(エンディアン)には注意しとかないと
万が一エンディアンの違うシステムで動作する必要があるときに死ねます 質問です。
とあるクラスのヘッダーに定義している文字列変数(CString)の文字列だけを変更し、ビルドしても、変更が反映されないのですがこれは仕様でしょうか?リビルドすると反映されます。
環境はVisualStudio2015 VC++です。 >>95
テキスト形式は、装飾次第で肥大化しやすいってだけだよ。
カンマやタブや改行も装飾の一部。
一桁の数字でも、スペース等で桁合わせしたら、それだけで肥大化するしね。
実際のところは、どういうフォーマットで出力してるか次第だけど。
最小桁で出力していて、rand 出力が正規分布に従うと考えれば、計算上約29k byteになるよ。 無名名前空間内の変数にstaticがついたものを見かけました
このstaticにはどのような意味があるんでしょうか?それぞれ同じような意味だと思い込んでいたのですが・・・ >>104
黒魔術できるから楽しいぞ。
入ってくれ。 auto R = Handle.ConnectTCP(...).WaitConnect().SendData(...).EndSettion();
auto A = Array.Map(...).Reduse(...).get();
こんな感じのことができるようになる。上は適当。
入ってくれー。 EndSession(SendData(WaitConnect(ConnectTCP(Handle, ...)), ...));
を
Handle.ConnectTCP(...).WaitConnect().SendData(...).EndSession();
と書けるようにしたいと、そんな感じか?
元ネタの言語はなんだ?お兄さん怒らないから正直に申告しなさいw まあSettionとか言う奴のレベルはこんなもんだ >>109
そう書きたいなら最初からそういうAPIにすればいいだけなんだよな タイムアウトとか再試行とか異常系コードがてんこもりに入るんだからどうせ分解して書く。
そういう書き方をしたがる人は実務では一切コードを書いてない人だろう。 >>112
異常系を入れる場所も階層も選ばないとか昭和初期のプログラマーーカヨ;
ていうか>>109の書式のどっちも分けて書こうと思えば書けるし… ちょっとしたスクリプトとかの書き捨てならワンライナーって言うのもわからなくはないけどC++には要らんわな 質問です。
int型のポインタが指す値に1を足したいのですが
int *a+=1;と書くと足されるのですが
int *a++;だと足されません
これはなぜでしょうか? なるほど!
カッコを付けてあげれば良いのですね
ありがとうございました。 基本解ってないバカはC言語からやり直せ
C++なんぞ十年早いわ >>120
演算子には結合の優先順位があるからそれを理解しておけということかと。 次はきっと評価順序に依存性がある複数の副作用を同じ式の中でやって泣く よし、>>116 からの流れを一言でまとめてやるぞ
必要なときはカッコつけなさい
こうだ >>117
おまえ病院に行ったほうがいい
変数aの定義でとち狂っている>>116より重症だぞ >>109
Dにもあるらしいけど、元ネタは没になったペーパー。 >>129
初心者が質問でおかしな書き方したが、周りはその意味が分かって会話が通じているんだから、そんなつまらない攻撃的なツッコミする必要ないのでは? >>131
意味わかった気になってるのは陽性症状だよ
幻視でint *a=+1;が見えた禁治産者がなに必死こいてんだ? 妖精症状かは不明だが『周りはその意味が分かって会話が通じている』という決め付けは危険だし
なにより相手に対して何の説得力も無い >>135
よくねえよ
int ++*a; で何を宣言できるんだ 誰も変数の宣言を問題にしてないと思うよ。君を除いて。 知恵袋とかでよく見る質問者に説教してる奴まんまだwww 周りがわかってるかどうかはわからんけど>>117はわかって質問者の>>116と会話できてるからいいんじゃね? >>141
requires { typename T::type{} }
は文法的に正しいですか? >>137
それが本当なら揃いも揃って阿呆ばっかりということだ
int *a+=1;で何が起きるのかを論じてこそC++の話だ
スレ違いの阿呆どもは出て行け スレを私物化しててワロタwwwwwwwwwwwwwwwwwww >>143
そんなの使うな、で終わり。
議論する価値は無い。 うむ、これで>>116の話は終わりだな
めでたしめでたし >>144
私物化はおまえだ
C++の話をしろボケ ひとつ手本を見せてやる
#define a aa{nullptr}; aa
int *a+=1;
#undef a
#define aa a
おまえら(たぶん1人)はこれ以下の阿呆だ typedefとdefineの違いすらわかってないのが俺
define A BだとAをBとする
typedef B AだとAをBとする
こうなるだけ? typedefなんかもう使うな
これからはusingだ >>150
#defineはソースコードのテキストを字面だけで置き換えるだけ。
typedef相当のこと以外にも色々な使い方ができるが、トリッキーなことをして分かりにくくなったり弊害が大きいので、言語仕様が拡充された現在では、なるべく使用すべきでないという風潮になっている。 defineは置き換えでtypedefは名前変更
#define SIZE 50, 200
void SetSize(int w, int h)をSetSize(SIZE)って呼ぶことができる
typedefはtypedef std::vector<MyLonglongClassName> MyVector;
とすることで短くできる >>151
>>152
>>153
defineは俺の認識であってると思ってるけど
typedefの名前変更ってなんなんだ
defineでもint hage ってしちゃうと名前変更にならない? typedefで導入した識別子の名称は、型の名前としてコンパイラが字句解析、意味解析する際に適切に扱ってくれるけど、defineの方は字面を置き換えただけだから文脈によっては意図した通りにならないケースがある。
具体例はすぐに思いつかない…
誰か詳しい人が書いてくれるかも。 typedef int *IntPointer; //A
#define IntPointer int* //B
//Aの場合: int x * const の意味となり、*xは変更可能
//Bの場合: const int *x と展開され、*xは変更不可能のためコンパイルエラー
void f(const IntPointer x) { *x = 0; } >>150
#defineは、厳密にはコンパイラの機能では無いんだよね。
ただのテキスト置換なんで、様々なチェックが働かない。
置換後のテキストに対してコンパイルを行うから、エラーも難解になったりする。
対してtypedefはコンパイラの機能。
型に対してのみ別名を付ける事しか出来ないけど、ちゃんと型チェックが行われる。 typedefを一切使うなというのは無理ゲーすぐる…
std::vector<std::vector<int> > jug_array = new std::vector<std::vector<int> >(5000);
for (std::vector<std::vector<int> >::const_iterator it = jug_array.begin(); it != jug_array.end(); ++it) {
...
}
とかゆうのはusingでは多分std::を削れるぐらいだと思う そのusingではなく
using hoge = int;
のusingだろ typedef名が無いとintのデストラクターが呼べない
using T = int;
int{}.~T();
typedef名が無いと関数ポインターへの変換関数が書けない(たぶん)
using F = void ();
operator F *() {return nullptr;} typedef名が無いと関数型をメンバーポインター型に変形させることができない
using MF = void () const;
MF class_type::* mp;
そして何より、関数内で#defineしたものは関数外に漏れる >>158
型推論でいいだろ
auto jug_array = new std::vector<std::vector<int> >(5000);
for(auto it = jug_array.begin(); it != jug_array.end(); ++it) {
...
} >usingでは多分std::を削れるぐらいだと思う
↓
>型推論でいいだろ
これがアスペというやつだな アスペかどうかはわからないけど話の流れを追わないで字面で反応する人いるよね %%%%1000%%%%
000-[HUM%58*73.1\%]/2I/3NM/61.3SNMK%?%3%51.22222222222221%
001-[[[%6/4$17.6135412α3]]]]+DOM+SIL+7%
002-UML7%[61.2[31.5[!%32∂LM17.36%!16.3!%<<<%!HSTOL7%!Q!S!=3m=<2TOL<3Q9A<2.1GHz%,DOK,HAOARA,
003-[[[HEMLOT47[<\41.2%Q,===>[MLS<DPNO<\2.3>#ESOLA!5%!3MLA!>LTOSA>7TONSA>%>%end CPUはアスペルガー
アスペルガーはプログラミング対象としては正しい そもそも>>158も>>163もコード間違ってるし
バカってなんで要らんところでnew使おうとするかね >>171
>>165 でアスペ認定された俺も思ったからお前もだな。 newはちょっと手が滑っただけ;
もちろんスマポとセットで無いとnewとか滅多に使わない >>176
糞ヴァカは二度と書き込むな
w付けたってお前のヴァカさ加減が軽減されることはないからこのカス >>178
まずはデストラクターの便利さを学んでね。 auto pointerのこと?
あれいつ見ても使うタイミングわかんないや
define typedefこたえてくれたひとありがとう
>>156のAのやつがなぜこうなるのか頭のなかでさっぱり理解できんけどがんばる >>181
Aの場合はint * const x の間違いだろう。
int*型という1つの型全体にconstがかかっている。 コードの書かない奴ほどC++をやっつけスクリプト言語化しようとする。
auto馬鹿どもを駆逐せよ。 >>177, >>185
動的型付けと型推論の違いも理解できない老害ははやくくたばればいいのに ヴァカが精一杯頑張って吐き出したクッサイ唾がこれ↑ > 動的型付けと型推論の違いも理解できない老害
は否定できないんだ w >>186
autoのことをanyやvariantと勘違いしてるとか? そんな勘違いしてるとなんで思い込むか全く分からんわ
まあヴァカの考えることなんて分かったら大変だけど こいつの脳内には「動的型付けと型推論の違いも理解できない老害 」
とやらが住んでいてるんだろうな。
それ少し前のお前自身の姿だからゲラゲラ 世の中バカばかり、自分だけがよくわかっている。
ってことでしょうか。 こいつプログラミング板荒らしまわってる某コテハンと同じ臭いがする まぁ、もうそろそろNG設定かね。俺は設定した。
大した技術持って無さそうだし。 2ちゃんねるのコテハンにはろくなヤツがいないって、戦後生まれのじっちゃんが言っていた。 そろそろ仕事やめて、めしにしようぜ
カレーライスとお子様ランチのどっちがいい? >>190
いきなりスクリプトとか言い出した理由書いてみ
どんな言い訳が見れるのか楽しみだよ w auto jug_array = std::vector<std::vector<int>>(5000);
という書き方は2012年ごろにさっちんとメイヤーが広めようとしていた
C++17でこの書き方が広まったら>>185はもう出家するしかない 良く考えずに書いたが良く考えたら普通は
std::vector<std::vector<int>> jug_array(5000);
と書くところだったなあ… UWPスレとか毛色が違うみたいだし、C++/CLIスレとか落ちてるんでここで教えて下さい
VS2017のC++/WinRTで新しいプロジェクトを作成
(Visual C++ → Windowsユニバーサル → 単体テストアプリ)
実行すると TEST APP 、Unit Test 、Tests Running の3つの文字が出てくるウィンドウが出てきます
しかし、UnitTestApp.xaml の Application要素の中身は、空っぽです
新しくブランクページを作ると、Page要素になって、デザインできる上にボタン等を貼り付けると
Page要素の中に要素が作られます
Application要素の中身は一体どこにあるのでしょう? >>205
そっちになるんですね、失礼しました、>>204は取り下げて移動します c++でダックタイピングのようなものをやりたいです。
void型で受け取ったクラスを自前で用意したインターフェースクラスにキャストして関数を呼び出すって可能ですか?
やり方や参考になるサイトなどあれば教えて欲しいです。
templateでの型消去はコンパイル段階でクラスを知らないせいで弾かれてしまっているようです…… vfptrの実装状況によるから、未知の抽象クラスのメソッドって
呼べないと思うんだが >>208
ありがとうございます
やっぱクラスの構成わかんなきゃアクセスしようがないですよね……
exeのlibに依存せずになんとかdll開発できないかと考えてたんですが無理そうですね
諦めます >>207
っinterpret_cast?
その代わり、ちゃんと素養のまともなモノを使わないとみ定義でPC死ぬからな。 >>210
ありがとう。これだと型確認回避できるのか……希望が見えてきました
ちょっと試してみます。 .outからsoファイル呼び出す形を作ってるのだけど
変数の共有するのってグローバル変数にするのとシングルとんみたいなの作る以外にある?
関数の引数にはできない状態だと >>216
グローバル「関数」内にstatic変数なんてどう?
ちょっと範囲が狭くなるけど、スレッドローカルストレージとかも。 >>200
OSや組み込み、ドライバでその書き方が広まったら認めてやるよ。
使い捨て、やっつけコードしか書かない小便垂れ小僧が。 >>216
俺は何かの設定じみたものは環境変数に入れとくこともある。
言語問わず子プロセスでも使えて便利。 OSと組み込みとドライバって特権階級かなんかなの? >>218がその世界しか知らない(それ以外は俺にはかんけーない)ということにじゃないかな OS内部とかドライバとか、位置によってはメモリ確保の方法変わってくるし
組み込みで動的にメモリ確保とか怖くってやってらんねーとかじゃい?
静的か自動変数にインスタンスの実体置くなら一応なんとかなるんだろうけど・・・
いや、静的だとコンストラクタがくっそ面倒か? auto とか生きてくるのって、
大抵ばかすかコンテナに要素しこたま抱える様な用途だしな いやautoの議論にケチつけたつもりは無いよ(俺も滅多にauto使わんし
C++の実用される現場といえばOS、組み込み、ドライバくらいしか挙げない人が多いから釘刺したかっただけ auto使わないとか頭固すぎ
使えるところは全てautoだわ 単なるシンタックスシュガーでなんのオーバーヘッドや副作用があるわけじゃ無いしな autoネタ大人気だな
俺もiteratorなんかじゃ迷わずauto使うけど
ポインタすらちゃんと理解してないような奴が無闇にauto使ってるのを見るとね 同じ話題ばかりで食傷気味、もう吐きそう。
…というこの書き込みも同系ネタで済まぬ。 >>229
auto を単なるシンタックスシュガーと言うのもどうかと思うが
とりあえず使わないと言う選択肢はないわ C++使わないとか頭固すぎ
使えるところは全部C++だわ 単なるシンタックスシュガーでオーバーヘッドとか副作用無いしねw ID:2A0a9mBA0 ←こういう馬鹿が本当にC++使ってるとは思えない。無職だろう。 auto絶対使わないマンってややこしい型も、全部手で書いてるの?
ET使うときとかどうしてんだろ。 テンプレートを除いた部分は単なるシンタックスシュガーだよ?
o->vftbl->f(o, a) と書こうが o->f(a) と書こうが何の違いもない。
テンプレートはチューリングマシンとしての計算能力があるから別だけど。 >>245
ET使う時って評価するときか?
auto a = b + c * d;
これやるとautoの型は式テンプレートで、評価が起きないから困ったことになるぞ
(まだ評価せずに組み合わせる場合は逆にautoが便利だけど)
ET作るときや実装時は確かに型がややこしいけど、普通returnの一文で終わるから
return {うんたらかんたら};
で済むと思う
あと、ET周りの関数の宣言時をautoでやってしまうと、実装完了まで使用できないというのが足かせになると思うぞ auto使うのって例えば
template <class U, class V>
auto func(U& a, V& b) -> decltype(a + b);
みたいに戻り値の型が簡単に推測しにくい時に使ってるけどな auto LocalFunc = [&]() { ... }; >>248
そのautoは型推論のautoとは違う使い方だよね。
戻値の後置宣言都合によるプレースホルダ的な。 mapみたいな複数行にまたがるようなのを
for( auto const & r: hoge ){}
とかにまとめる用途にしか怖くて使えんな
意図しない型になってたけどたまたまコンパイルに通ってたとか
後で仕様変更とか根元の hoge 書き換え後にたまたまコンパイルに通ってたりとかで
期待したメソッドの動作にならなかったりとかされるとハマりそうで怖い >>252
暗黙の型変換乱用しないかぎりそんな事ならんと思うが >>253
暗黙の云々とかoperator=とかが怖いってだけ
それに後から読み返した時、どんな戻り値が欲しかったのかとか
autoだとわかり辛いって事がままあるし、autoはなるべくあちこちに散乱させたくない
.NET方面のvarとかも気持ち悪いったらありゃしない・・・ autoの数々の利点のほうが大きいからどの言語でも型推論は基本になってきてるな
メイヤーズも言ってるしマイクロソフトも推奨してるし autoはどのように推定されるかを理解して使うもので、
断じてバカ用のヘルパーではない
バカ自身はそれがわからないから変な杞憂に陥るってだけ バカだけどIDEさんが、IDEさんさえいてくれれば大丈夫だ問題ない 初心者はまずauto使わずにプログラミング出来るようになってからにした方がいいね auto使わずにコンパイラの警告レベルを最高、警告は即エラーって設定にして
テンプレートライブラリ使ったテストプログラムを書いてみると
autoのありがた味が分かると思う。
ループの制御変数の型がえらいことになったりするからな。
いわんやイテレータをや。 例えば
Bar x;
auto z = x;
としたときに、zはの型は必ずBarになってBarの基底クラスになったりしないの? Barの基底クラスがFooだとして、
実はBarはコピコンがprivateでなぜかoperator Foo()だけがpublicで定義されているかもしれない
かもしれない運転、 あるいは
class Foo {
void assign(const &Foo) { ... } // (A)
};
class Bar : public Foo {
void assign(const &Foo) { ... } // (B)
};
Foo x1, x2;
Bar y;
auto z = x1;
z.assign(x2); // (C)
y = z;
とかなときに(C)で呼ばれるassign()はどっち? 参照なしのautoで代入だから、この場合は同じ型でコピーだね。メソッドは仮想関数でもないから、同じクラスのメソッドが呼ばれるはずだ。 C++で起き得るBarとFooのパターン全てについてテストケースを考えるのは無理ゲーすぐる、
auto儲はどのようにして有限の人生と無限に近い(ときに想像を絶する結果をもたらす)C++の自由度との折り合いを付けているのであろうか… かしこいIDE使ってるなら、ビルドしたらその場でautoの型がわかるはず。スマートに行こうぜ、スマートに。 struct S {};
using Bar = S const;
Bar x;
auto z = x;
必ずしも同じ型ではないな >>263
それがどんな問題が起きると?
>>264
Bar使われてないじゃん 大量のC++のコードを読み、大量のC++を書いてきた人は今更シンタックスを変えようとは思わない。
碌にコードを読んだことがない、書かない人が文法を変えたがるのだ。
外国人の日本語入門者が「は」と「が」が難しいからautoにしろ、どっちの意味かは読む人、聞く人が考えろと言ってるうなもの。
ひらがなとカタカナを統一しろとかね。日本人ならそうは思わない。日本語を使い続けて必要な理由を知ってるから。
日本語から「が」がなくなれば不便で仕方がない。
だからauto使いは大学デビューとか言われるのだ。未だコードネイティブではないのだ。
10年使ってからautoが必要かどうか考えろ。答えは明らかだ。 > 大量のC++を書いてきた人は今更シンタックスを変えようとは思わない。
これは嘘
autoだけでなくtrailing return typeやusing aliasなど
かゆいところにやっと手が届いたシンタックス変更は大歓迎している
C++11以後に拒否反応しまくって、未だにC++98のマゾプレーを続行中の変態は
頭固すぎだ
# 自分で言うのも何だが、俺に頭固いなんて言われるのは極端すぎだ >>270
藻前の呼びたかったassign()は実はFoo::assign()(基底クラスの方)だったかもしれないじゃん? ところでこれからC++を始めたいのだが、純粋にC++が始めたいのではなくてc言語の代わりとして
C++を使ってみたい。多少なりともC++の方が便利だろうとおもうから。一つ二つ制約があって
ROMが256バイトしかない。RAMが8Kしかない。こういう場合に今までROM48Kバイト、RAM8K
バイトでおさまっていたプログラムをC++で移植するのは余裕だろうか? それとも便利になる分
スペースがとられてRomエリアが少なすぎるってレベルだろうか? >>271
要出典:auto使いは大学デビュー
ラムダ式を変数に入れたいときはどうやるの?
コンテナのイテレータを変数に入れたいときは型名全部書くの?
std::bindの戻り値を変数に入れたいときはどうするの?
何でもかんでもauto使うのはどうかと思うがこういう面倒なところはautoでいいんじゃね >>274
メモリーをけちるなら、STLとかテンプレートとか呼ばれるものはあまり使わない方がいい。
std::coutなどのストリームもダメだ。あれは遅いし、バカ食いする。 >>274
256KBの間違いだろ?
まずは、メソッド、デストラクタ、std::stringの3つを学習してみな。便利だとわかるから。 >>274
ROMは256Kの誤記だとして
RAM8Kはきついな
マイコン向けの開発環境も無償版や評価版なんてのがあるから一回試した方がいいと思う
コンパイラのオプションで例外と実行時型情報はOFFにするのを忘れずに
C++のコンテナクラス(std::vectorやstd::string)はメモリ不足で使えなさそうだな ROMは256kの間違い。外部RAMは256kbある。(ただしSPIでアクセスするので遅い)
だから8kは純粋にワークとして使える。
8kのRAMがきついと思うのは何故?
C++もワークはスタックを使うと思うけど、プログラムの実行エリアとして例えばクラスインスタンスを
作るのにRAMを消費することになるんだろうか? 動的にインスタンスを作成するとそのクラスが大きいと
RAMエリア(mallocで確保してロードしたら、解放するまではRAMエリアを使う)を圧迫することになる。
ということはRAMをあまり消費しない手法ってあるんだろうか? 普通は処理系が要求するコード、CONSTデータ、、スタック、初期値付きデータ、BSSの各セクションを
プログラマーが明示的にリンカに指示して割り当てさせるんじゃね;;
これはCもC++も同じなのでCでのやり方を理解しているなんならC++でも同じようにやれば良い
(グローバルなオブジェクトの構築と破棄の手当てが追加になるだけぐらいしか違いが無い >>282
最適化切って動作確認したり、デバッグ用のコードを仕込んだりしてると8Kは意外とすぐに使いきれてしまう
当然プログラムの規模や書き方によるところだから必ず足りないわけではないけど
C++だから足りないというわけではない
元のプログラムがCで書かれてて8Kで動いてたならまぁ大丈夫か >>282
>8kのRAMがきついと思うのは何故?
全てはID:5nFESEae0が上記各セクションをROMやRAMにどのように割り付けようとしているのかにかかってゐるのだが、
仮にスタックと初期値つきデータとBSSを全部8 KBのRAMに割り付けた場合、
コード以外の全て(malloc()含む)のメモリ消費がトータルで8 KBに収まらねばならず、
メモリ不足のせいでやれることは相当にきびしくなるとおもー ID:XRmGRjwZ0
> RAM8Kはきついな
> コンパイラのオプションで例外と実行時型情報はOFFにするのを忘れずに
> C++のコンテナクラス(std::vectorやstd::string)はメモリ不足で使えなさそうだな
こいつレベル低すぎだろ。ド素人にもほどがある。
完全に組み込み経験なしじゃねーか。学生じゃねーのか。 sizeof(コンテナクラス)すればワカル、
ただしコンテナに要素の追加でmalloc()される分は別枠 >>274
論外 勉強目的だろ
自称プロでも 8kB なんて環境で組んだことのある人間なんて少数
普通はデフォルトのスタックサイズやvtableの存在すら知らん
考え直せ Microchip マイコン PIC24FJ128GA006-I/PT 16ビット RISC PIC24FJ,
32MHz, 128 kB フラッシュ, 8 kB RAM, 64-Pin
http://jp.rs-online.com/web/p/microcontrollers/6230897/
8KB RAM は、400円のPIC マイコンとかだろ
そもそも、C++ のコンパイラが無い コンパイラはありますよ。C/C++とうたってるので恐らくC++もできると思うが、、、
TIとかHewとか他にもKeilとか >グローバルなオブジェクトの構築と破棄の手当てが追加になるだけぐらいしか違いが無い
おお、心強いお言葉。
例えば
class MyClass
{
int buf[1000];
int no = 0;
void inputdisp(int aa){
sprintf(buf," aa=%d",aa);
}
};
int sub1()
{
MyClass aaa;
aaa.disp(333);
return 0;
}
こういう場合はaaaはbufは2000バイトのRAMを使うけれども、stackに確保するんだろうか?
aaa自体はrom上にできると考えていい?
それなら、cと混在で徐々にC++に変えていく程度でも問題ないのかなとは思っている。 >>292
>aaa自体はrom上にできると考えていい?
質問の意味不明 再入力せよ 動的にNewを使ってインスタンスを生成した場合には、コードは必然的にRam上に置かれる。しかしスタティックに
生成した場合は、Code部分は原理的にはRom上にも置くことができる。そういう機能があるかどうか?って質問。 >>294
>動的にNewを使ってインスタンスを生成した場合には、コードは必然的にRam上に置かれる。
断じて否
こういう手合いに騙されてはいけない >>292
aaaもbufも同じ場所。大抵のコンパイラでは同じアドレスを指す。C解るならclassをstructに置き換えて考えたらいい。それと一緒。 ていうか>>294ハ質問者本人かしつれいorz
>>292のMyClass::inputdisp(int aa)のコードは、名前が適当にマングルされて(*1)
void hoge(MyClass* this, int aa) // (1)
という2引数の関数としてコードセクションにコードが格納される、というのが真実(*2)(*3)
オブジェクトaaaを動的にNewを使ってインスタンスを生成しようがスタティックに生成しようが、
そんなこととは無関係に、aaa.inputdisp((int型データ))というメソッドの呼び出しは(1)の関数呼び出しにコンパイルされる
*1: ここでは簡単のため’hoge’という名前にマングルされたとしている。本当は引数の型や戻り値も情報として含む名前になるが省略
*2: C++の言語規格でそうせよ決まっているかどうかは知らないが、そう処理する処理系しか無いと思う
*3: コードセクションがROM上なのかRAM上なのかはプログラマーがコードセクションをどう割り付けたかによる >296
うろ覚えで使ってるが、
Section Type of Memory Section Type of Memory
.bss RAM
.stack RAM
.data RAM
.sysmem RAM
.text ROM これがコード部分
.その他 ROM
こういうのがある。
Hewの場合#pragumaでセクションを生成できたとおもうが、一般的に#pragma とかで割り当てできるんだろうか?
今回はTiのコンパイラを使う予定なので初めての試み。
多分
static Myclass aaa;
みたいにスタティックかなにかを冠して宣言すれば.textにコードは配置されると思うが、どうなんだろう。
スタティックなんだから原理的には配置はどうにでもなる筈。 問題はスタティックにした場合, コードは.textに配置されるとしてもdataが.dataに配置されると非常にまずい。
スタックでやってもらえないと困る。 >>300
関数が再入されることを考えたら普通にスタックに配置されると思うよ。
むしろstaticにしたらスタックには配置されない。
ここまでインスタンスの話。
コードはいずれにしても.textに配置されると思うよ。特に指定がない限り。でもそれは>>300にとっても問題にならないかと。 >>289
30年ぐらい前に ROM2KB, RAM2KB の Z80 ボード用プログラムをC言語で作ったことあるよ。 例えば、パネル表示をまとめたクラスのような場合にはクラスのメソッド部分が非常に大きくなる。しかもライブラリ
的に使うわけだから、階層のわりと下で使うことになる。3階層あって、2階層目くらいから同時にいくつかが
生成されてしまう可能性も高い。するとRAMエリアが直ぐにパンクする。なのでメソッドを大量に含んだライブラリ的な
働きをするクラスに関しては、.textにあってほしい。それは可能だと思うがじゃあそのクラス内でつかうバッファなどの
変数なんかが問題になる。これは動的に生成しないとクラスの使い道が非常に限られてくる。第一suba()で使っていて
subb()で使うとバッファエリアが壊れてしまう。
1.bufを持てないクラスなんて殆ど意味がない。
2.bufをスタティックにしか配置できないクラスなんて使い道がない。
3.小規模マイコンでメソッドをramに確保するなんて馬鹿げている。
これは明らかだよね。
つまりMyclassのbuf[1000]、メソード関数()(例えば50個)をスタックと.textにそれぞれ上手く配置する工夫が
絶対に必要ってことだね。 >コードはいずれにしても.textに配置されると思うよ。特に指定がない限り。でもそれは>>300にとっても問題にならないかと。
であれば何も問題ないですね。 組み込みはPCで動くの違って配置も考えないといけないから大変だな
マイコンでの配置に関してはここより組み込みが普通の電電板のマイコンスレでの方が良いような気がするが。 >>274
純粋にC言語の書き方するだけならコンパイラの能力次第だと思う ヘッダファイルに型定義して、実装をCPPに書くのってどうかなーと思う。特に組み込み
だとファイルを分ける意味がわからない。分けるとクラスのイメージが掴みにくい気がする。 >>307
コンパイル時間短縮とか中身の隠蔽とかしたいなら、ソースとヘッダーを分けてもいいんじゃね? >>307
その定義した型を他のファイルから使う時はどうするのさ?
単一のファイルしか使ってないなら分ける必要はないけど クラスってのは型の定義なんだから、使う時は全部インクルードではだめなの?
例えば
clsAAA.h
clsBBB.h
...
clsXXX.h
main.cpp
の中で
include "cls\clsAAA.h"
include "cls\clsBBB.h"
....
include "cls\clsXXX.h" >コンパイル時間短縮とか中身の隠蔽とかしたいなら、ソースとヘッダーを分けてもいいんじゃね?
100個くらいクラスがあってもどってことないと思うが、、、ロード時間が問題になるんだったら
clsディレクトリにクラスファイルを入れて
prtディレクトリにメソッドを実装しない型だけ抜き出したのを入れといて、xxx.prtをインクルードする
方がいいと思う。 やっぱりメッソドがデータなんかと分離するのはわかり難い。他のオブジェクト指向のコンパイラでもそんなことはしないしね。 ヘッダだけだと循環参照起きるし、循環参照起きるところだけcppってのも気持ち悪い >>313
分けなきゃいけないことはない
分けた方が効率が良い(場合が多い)というだけだから
理解した上で敢えて分けないならそれはそれで好きにすれば良い >>314
inlineキーワード使って定義もヘッダーに書いちゃえば? >>307
> ヘッダファイルに型定義して、実装をCPPに書くのってどうかなーと思う。
>>310
> クラスってのは型の定義なんだから、使う時は全部インクルードではだめなの?
いったい何をどうしたいのかさっぱりわからん >314
前方宣言でいいのでは?
そういうのは特殊な場合だけだから >>318
class Aからclass Bのメソッドを呼んで
class Bからclass Aのメソッドを呼ぶ場合前方宣言だけでは無理なはず >>319
宣言を両方最初に書いておき、定義を後に書く。 >>320
class Aとclass Bが同じファイルで定義されてるならいいかもしれないけど、そうじゃない場合のほうが多いでしょ いづれにしてもメソッドをばらして別ファイルに書くほうが良いという根拠にはならんだろ。 一部分けなきゃできないところがあるから全部分けるだけで、できるならc#とかみたいに全部一つのファイルに書きたい それだとクラスが縦に長くなって範囲がぱっと見わからなる
1クラス1ファイルの場合はいいけどさ てかコードの利用者はヘッダしか見ねーんだから普通に分けとけよ >323
できないところってどんなところ? C#にできてC++にできないなんてどういうことか意味わからん。
cls::とか邪魔くさい。悪しき慣習だろ。あまりにばかげてるからC#では止めにしただけでしょ。 >>323
一部だけ分けりゃいいじゃん
それとシングルソースにしちまうと分担がしにくいだろ >>327
ヘッダとソースを分けないでって意味でシングルソースってことではないと思うぞ モジュールについては検討中みたいだからそのうち仕様に入るんじゃね?
コンセプト並みのビッグトピックだからどんどん後ろ倒しされそうな気もするけど。 vector<shared_ptr<T>>を使う場合、
shared_ptrから自分自身のvector上のindexを取得するにはvector要素を1つずつ走査していくしかないんかね?
vector[0]のアドレスをうまく引き算すればうまくいくかと思いきや、
shared_ptr自体は同じアドレスを持つインスタンスがvectorに格納されているわけでないのでうまく行かんのです >>330
基本的には無理。
何らかの基準でソート状態を保たせていれば、バイナリサーチ系の処理(lower_boundとか)が使えるので、必ずしも一個づつチェックする必要は無い。 もしindexが変わらんのであれば別にmap<shared_ptr<T>, int>持つとか
Tにindex持たせるとか cppで作ったライブラリ(.a)をcに取り込むときって何か注意いる?
cppには公開apiを1つ用意して、そのなかでクラスを作って計算させようとしてる >>333
その公開apiをextern "C"するのを忘れない事。 extern "C" しとかないと大抵はリンクの段階で失敗してくれるから、そんなにおかしなことにもならないだろうけどね。
あとは C++ 側で作ったライブラリから例外が送出されると C 側を通過できなくてクラッシュする環境がある。 >>300
やり方しだいジャネーノ?C++推奨しないが、スタックが〜 ramが〜っていうなら自分で管理するか、newに任せるにして実験すればいいんじゃね?
#include <stdio.h>
#include <string.h>
char buf_hige[1000];
class Hoge {
private: char *m_pBuf; int m_size, m_IsNew;
public:
Hoge(char *p, int s) { m_size = s; m_pBuf = p; m_IsNew = 0; }
Hoge() : m_size(100) { m_pBuf = new char[m_size]; m_IsNew = 1; }
~Hoge() { if (m_IsNew) { delete[]m_pBuf; printf("~Hoge()自動削除\n"); } else printf("~Hoge()\n"); }
void zero() { memset(m_pBuf, 0, m_size); }
void show() { printf("アドレス %p size %d\n", m_pBuf, m_size); }
};
void main() {
char buf_hoge[200];
Hoge a(buf_hige, sizeof(buf_hige));// 自分でメモリー割り当ててクラスを使う 普通は ram.. #pragmaとかで移動できる?
Hoge b(buf_hoge, sizeof(buf_hoge));// 自分でメモリー割り当ててクラスを使う mainのstack
Hoge c;// 内部でnew/deleteして動的に使う ram
a.zero(); b.zero(); c.zero(); a.show(); b.show(); c.show();
} 普通の opereter new 定義するだけじゃ駄目なの? その例なら m_pBuf とか m_size とか m_isNew がどこに置かれるかって話してるんだよ >>300
リンカスクリプトで定義できるんじゃねーの >>331
>>332
返信thx
やっぱむりかー。index持たせる方向で検討します >>338
リンカーでMAP指定して確認したらいいんじゃねーの?アドレスわかるだろ? 共用体って使い道あるの?
素人目からしたら役に立つようには到底思えない 使わずに済むならそれにこしたことはないだろうけど、
部分的に動的型みたいにしたいときは有るよ。
yacc が生成するコードに出てきたりする。 >>342
例えば通信パケットとかで必ず固定長だけど、複数の箇所のコマンドとか意味とかのコードで
内容がコロコロ変わる様な時は便利かも知れない?
それぞれの構造体にキャストしろよって言いたくもなるけど、
複数の人で開発してると通信パケットの内容とかで下らない不具合出したくないから
1つのヘッダで全部規定したりって事はあったな あ、後H8開発してた時とか、メモリマップドIOとかがモードでコロコロ意味変わる時、
1バイトのデータになったりビットフィールドになったりなとことかがunionになってた union RGBA{
struct {R:5,G:5,B:5,A:1};
std::uint16_t Colors;
};
こんな感じのことするけど。たまに。 あ、片宣言抜けてた。
たまにしか使わないからなぁ。
struct {std::uint16_t R:5,G:5,B:5,A:1}; union { double d; int i; char c;} u;
は1番大きな要素、この場合は double d のサイズと
メモリアライメントを持つというのが union の重要な機能
これのおかげで非ワード境界からワードを読もうとするようなコードを避けられる #pragma data_seg
でdllの共有領域を作ってるんですけど
ここにクラスのインスタンスを置いておくことはできますか? コンストラクタのない、構造体にメンバ関数付いただけのクラスのインスタンスなら大丈夫じゃないかな。
動的にメモリをアロケーションするクラスではアロケーションしたメモリは共有されないので注意。 ↑
共有されないってのは「プロセス間で」ということね >>348
『プログラミング言語C』のmalloc()の実装例のやつで見た 共用体は、パリティチェックで使う
あるサイズの内容を、ある方法で計算して、データが破壊・改変されていないか。
通信データが正しいかどうか >>349
確保済みのメモリブロックに対してのobject new 演算子ってのが
あるはず string::format()マダァー?
<<は失敗だったって早く認めようぜ printf()系関数とstring::c_str()(ていうかbasic_string<T>::c_str())があるから無問題 入力はscanf()系とか使うとCの経験が長いプログラマーには軽蔑の眼差しで見られるが
cinとかより速くて使い勝手も良いのだから仕方が無い 可変テンプレート使えるんならprintfにクラス喰わせたりすることぐらいできるだろ snprintfじゃstringstreamの代わりとしては役者不足だろ >>362
しかも「役不足」じゃあ、「役より実力が遥かに高い」の意味だしね。 >>361
全然wwwwwwwwwww
自作クラスのシリアライズ/デシリアライズの下請け関数として使う分には
機能上全く困らない上に速いのだから
で、シリアライズ/デシリアライズおあ
void ISeriarizable::seriarize(FILE* fp)とvoid ISeriarizable::deseriarize(FILE* fp)
にして「<<」や「>>」のオーバーロードみたいな変態じみたことはせずに同等の柔軟性を確保できる
cin,cout って組み込みで使えるんかい?
何処をどう書き換えるとそうなるん? string s1("foo");
const char *p = NULL;
p = s1.c_str();
cout << p << endl;
return 0;
????
cout << s1<<endl; じゃダメなん? Coutを実験してみたがコードがバカでかくなるので駄目だな。組み込みでは使えない。 >>369
組み込みで何をやりたいのか知らんけど普通coutを書き換えるだろ 組み込みに使うなら実験とかじゃなくちゃんとどんなコードか把握しろよw怖いわ そもそも組み込みの標準入出力がどんなもんなのかすら想像できないw 組み込みでは使えないなんていう次元ならそもそも標準ライブラリ使わないだろ デバッグ担当「なぁ?なんかログにアホとかハゲとかあるんだけどナニコレ?オレの事おちょくってんじゃねーだろうなぁ?!あ!!!!」 streamの変更ムズいんだけど。
入力だとstreambufのunderflow実装すると思うけど、エラー発生したときどうやってistreamに通知すんの? struct lock_interrupt {
lock_interrupt() : masked(get_imask_ccr()) {
set_imask_ccr(1);
}
〜lock_interrupt() {
set_imask_ccr(masked);
}
bool masked;
};
// in some function...
lock_interrupt lk;
// do critical action, lets forget unmask interrupt flag!
}
このコード lock_interrupt() : masked(get_imask_ccr()) {
ここの部分の”:”ってどういう意味なの?
何となくコンストラクタとディストラクタがせっとになってるだろうなー
だから”}”に出会うと自動的にディストラクトされるコードだろうか?
ってくらいしかわからないレベルだから、、、、是非ともこのコードを
使い倒してみたい。 メンバイニシャライザでググれ
てか初等文法くらい勉強しろよ >組み込みで何をやりたいのか知らんけど普通coutを書き換えるだろ
ん?
普通はcoutを使わないという意味だろうか? それなら同意する。
#include <iostream>
を追加しただけで256kbyteを超えてしまう。これではマイコンじゃ使えないな。
もちろんcoutが使えないって意味だよ。使えないなら書き換える? まあそれは
むりだな。なぜなら書き換える場合でもiostramをインクルードするひつようがあるからね。
つまり書き換えなんてできない。つまり使えないし使わない。すなわち結論としては
Cのsprintfを使うってのが順当かと思う。 >>376
あとついでにクラス全体を説明すると、コンストラクタで割り込みをマスクして
デストラクタで元に戻している。
こんな感じで使う
void foo () {
lock_intterupt lock; // 以下割り込み禁止
if (...) {
....
return;
}
.....
return;
}
割り込み禁止を解除するコードを書き忘れたり複数書いたりせずに済む。 >メンバイニシャライザでググれ
キーワードありがとう。
ググってみた。メンバーイニシャライザってことはわかったんだがなんか特殊だな
masked = get_imask_ccr();
こういうことか? なるほど。 ここでlockという名称は何でもいいんですよね。要するにstructを生成するだけだから。
2か所でlockしたいような場合には使えないという欠点があるね。
void foo() {
lock_intterupt lock; // 以下割り込み禁止
if (...) {
....
return;
}
lock.unlock();
.....
.....
.....
lock.relock(); // ここでも割り込み禁止
if (...) {
....
return;
}
.....
return; // ここでlock(割り込み禁止)した部分が解除される。
}
こうするにはどうしたらいい? なんでclassにしないでstructなのだろうか? C++の本見るとcout,cinの例が必ず出ているが、これは大きな間違いだな。なぜなら
1.マイコンではiostremは馬鹿でかくて使えない。だからcout,cinは使えない。
2.じゃあパソコンで使うのかというと、パソコンならjavaかC#があるのにC++なんて
使うのは間違い。
以上の理由からサンプルにcout使うのは馬鹿。 というか、もっとmiimaizeしたiostream実装しろよな。といいたい。 >>381
> 2か所でlockしたいような場合には使えないという欠点があるね。
ブロックも知らんのかよ...
void foo(){
{
lock_intterupt lock; // 以下割り込み禁止
if(...){
...
return;
}
}
...
...
{
lock_interrupt lock; // ここでも割り込み禁止
if(...){
...
return;
}
}
return; // ここでlock(割り込み禁止)した部分が解除される。
} >>ブロックも知らんのかよ...
そういうのがあったのか。 ブロックってスコープだけの問題ではないんだ。
スコープ外れるとディストラクトされるんだ。
いがいと使えるなー。 >メンバーイニシャライザーなんて上級者向け
イニシャルなんて基本中の基本なのに、上級者でしか使えないほど分かりづらい構造になっている。
素直に=をつかったらいいのにな。 lock_interrupt(){
masked = get_imask_ccr();
set_imask_ccr(1);
}
これでいいじゃん。 物知らず自慢されても周りの人は当惑するだけですよ。
メンバーイニシャライザが何故必要なのかはメンバーイニシャライザでググってください。 メンバーイニシャライザでググると
メリット1:const指定のメンバ変数の初期化ができる
メリット2:メンバイニシャライザの方が効率的
メリット3:クラスを継承する場合は、メンバイニシャライザに基底クラスのコンストラクタを記述します。
メリット4:メンバイニシャライザを使えるようになると、プログラミングが上手になったような気分になれます。
とあるが、
1はあまり意味がない。constを初期化しないで使うケースは皆無。
2は理由が不明。わかり難いし、効率が変わる理由がない。効率を変えることができるなら、コンストラクタの効率も上げればいいだけだ。
3も意味不明だ。基底クラスのコンストラクタをイニシャライザに記入する必要性がないと思うが、出来ないのか? この方法でしか
できないのならそれはデメリットというのが正しい日本語だ。
4はこれが最大のメリットだろうな。 結論
テクを自慢したい人以外はメンバーイニシャライザは使うべきではない。 >>393
代入するまでそれがどういう状態になるのか考えた? >代入するまでそれがどういう状態になるのか考えた?
ん? constとは定数ですよ。代入なんてありえません。設定です。コンパイラーがシコシコ考えて設定済みです。
プログラムが走る時には最初から決まってるもの、最初を決めるのに別にイニシャライザで
やろうが、コンストラクタでやろうが関係ないです。はい。
ちがった? 初期化と代入の違い
constとコンパイル時定数の違い >>398
適当にググって済ますんじゃなくて真っ当なc++本を一通り読んでから帰ってこい。
あと組み込みを前提に考えるのもやめとけ。 >>398
> constとは定数ですよ。
残念ながら違う
class c {
private:
const int n;
public:
c(const int x): n(x){}
...
}
なんてことができる メンバーイニシャライザの構文は必要悪
だとは感じる
基底クラスやconstメンバの初期化構文が別途必要だったというのは必要悪ながら必要性がワカルが
その他のメリットはあんまはっきりしない >class c {
>private:
> const int n;
>public:
> c(const int x): n(x){}
> ...
>}
>なんてことができる。
定数ではなくて、変更禁止の変数ってことだね。それにどれだけ意味があるんだろう。
イニシャライザ―でしか変更できないんでしょ。クラスを生成したときにしか設定できない変数になる
から、定数と同じ機能しかないよ。
const int n = 9600;って書く方が分かりやすい。
しかし別のインスタンスを生成する時は
c rs(115200);みたいに初期値を変更したい場合がある。これを実現できるのはイニシャライザ以外にはないってことか。
なるほど。
全く意味がないってことはないな。たしかにメリットはある。 結論を変更
メリット1:クラスのインスタンスごとにconst指定のメンバ変数のユニークな初期化ができる
メリット2:const指定のメンバ変数はユニークに設定できるにも拘わらずコードをまったく消費しない。 >>405
まあ構文はわかり辛いよな
int n; で定義してるのに : n(1) とかはあ?って感じだし
かと言って c(): n = 1 {} って言うのもなれてないせいかいまいちだしね コンストラクタの構文があるんだから並置してつくるべきだね。
たとえはこんな感じだ。
class cass {
private:
const int n;
public:
cass(const int x){}
cass{ n = 9600 }
...
} ~cass()があるんだから
!cass()でもいい。 >>406
> const int n = 9600 って書く方が分かりやすい
C++のconstは、ユーザー入力など実行時に決まる値に固定化した変数を作れる >>410
こいつはコンストラクタを複数持てることも知らんのか...
マジで初心者スレに行けよ
【初心者歓迎】C/C++室 Ver.102【環境依存OK】
http://mevius.2ch.net/test/read.cgi/tech/1509780815/ >>412
そう言う意味ではC#のreadonlyの方が近い感じだな >C++のconstは、ユーザー入力など実行時に決まる値に固定化した変数を作れる
実行時は無理でしょ。インスタンス生成時でしょ。見かけ上実行時にインスタンスを生成することで
可能というだけですよね。 >こいつはコンストラクタを複数持てることも知らんのか...
オーバーロードってことかな? イニシャライザとはなんも関係ないね。 >あと組み込みを前提に考えるのもやめとけ。
C++は組み込みにしか活路がない。というか組み込みに特化すべきだと思う。
PCの場合はJavaとかC#の方が圧倒的にいいからね。
組み込みにCではなくてC++を使うべき最大の理由は?
最大のメリットはScopeが使えることだと思う。NameSpaceとかブロックとかだね。
まあClassの基本構造もスコープを制限できるという意味では含める。これらを使うだけでも
価値がある。
Cでは少しプログラムが大きくなると名前付けで混乱してくる。多少はコード効率が落ちてもC++の方がいい。
C++はすでに化石かと思っていたがなかなか使えそう。 多分パフォーマンス重視のソフトとか一つも知らないんじゃね 速度が要求される用途ということは、アセンブラの代替としての言語なのだ。
高級言語志向の奴はKotlinでも使ってろ。 C++で数百万行になるプロジェクトをアセで書けと? >>415
たとえばインスタンス生成時のシステム時刻をconst変数にセットするとする。
これを実行時と呼ばずになんと呼ぶんだ? メンバイニシャライザって、基本だろ。
初期化と代入は異なるから、マシン語も異なるし、効率的
君らは、実行ファイル中の、BSS セクションとか、
異なるセクションのデータが、異なるマシン語になる事も、知らんのか? >>423
そんなのはプロでもなきゃあまり知らないんじゃない? >たとえばインスタンス生成時のシステム時刻をconst変数にセットするとする。
>これを実行時と呼ばずになんと呼ぶんだ?
クラスを起点で説明するときには、実行時というのはクラスインスタンスのメソードを実行したり
プロパティにアクセスする時が実行時だね。
インスタンス生成時とは区別したほうが分かりやすい。
クラスは大まかには
1.生成して
2.実行して
3.消滅する
というサイクルがある。
constは生成時にしか設定できない。 >>426
少なくともC++においては実行時とは「コンパイル時」に対比する言葉だ。
「クラスを起点に説明する」なんて知らんがな
独自定義か? >>415
> 実行時は無理でしょ。インスタンス生成時でしょ。見かけ上実行時にインスタンスを生成することで
> 可能というだけですよね。
見かけ上?
意味わからん
インスタンス生成時=実行時なんだが w
>>416
オーバーロードしたコンストラクタ毎に異なる初期値を与えられるんだが>>410の構文でどうやって実現するつもりなんだよ w メンバイニシャライザの構文、
class Aclass {
public:
Aclass(int val) : _member(val) {}
...
}
の評判が悪いけど、C++11から使えるようになった{}初期化なら
いくらかマシじゃないかな。
class Aclass {
public:
Aclass(int val) : _member {val} {}
...
}
メンバに初期値を与える部分が関数呼び出しに見える、
という事態は解消されてるかと。 >>409
なんでそのnのケースで構文を新たに作る話になりますか… お前ら
T t(args);
って形の初期化付き変数宣言使ったことも見たこともない素人ばかりかよ...
インスタンスとクラスの違いも知らずに他人と話そうとする迷惑な人もいるし。 >>430
ん?
> まあ構文はわかり辛いよな
って言う日本語を理解できない人なの? >オーバーロードしたコンストラクタ毎に異なる初期値を与えられるんだが>>410の構文でどうやって実現するつもりなんだよ w
ass():{ assmember = 12; }{
....
}
ass(int you ):{ assmember = 99 }{
....
} >>434
しれっと>>410の構文変えてどうするよ w
>>410の時点じゃ知らなかったんだろ? 知らないでもすぐにまともな構文が考え付くというのに、わざわざ仕様を変更したというのに
またしてもろくでもない構文とは、どういうことだ。 こんな浅い思いつきだけで喋ってるやつによくつき合ってるな >>433
> まあ構文はわかり辛いよな
という国語はわかったつもりだったが>>409のような変態構文の追加提案に至る必然性がわからん…
そのケースならコンストラクタ内でn=1でええやん?
なお初期化と代入は違うという意見は
コンパイラのコピコン呼び出し回数削減最適化を前提とする限り、
あんまメンバ初期化構文の支持理由としては弱いかなと、(いうのが元レス>>405 >>438
コピー出来ないクラスはどうすんだよ。コンストラクタ内でのメンバーの代入はメンバーの構築とみなすという特殊ルールでも付けるのか? >>438
>>409の構文にケチをつけたいだけなのはわかったよ >>439
> コピー出来ないクラスはどうすんだよ。
const 云々言ってるなかで>>438みたいなレスする程度の理解力だから許してやれよ w
> コンストラクタ内でのメンバーの代入はメンバーの構築とみなすという特殊ルールでも付けるのか?
C#のreadonlyはそんな感じだな >>439
まあYESということもできる
クラスFooのメンバm_a (∈クラスT)は、Fooのコンストラクタ実行前に構築されているはずはないのだから
m_a = (some クラスTのオブジェクト)
というのがコンストラクタ内に現れたら、むしろそれを代入と解釈するわけにはいかない
すわなち話がただちにコピコンの出番に絞られる >>441
ちょっ漏れもconst云々は>>405で言及済みなんだがガン無視カヨ
何でも俺の仕業かよ…
>>440
いや新たな構文の追加提案自体の罪を問いたい
>>405の通り、基底クラスとconstメンバの初期化については現行のメンバ初期化構文は必要悪なんであって、
それ自体は全否定まではしないが、
基底クラスとconstメンバの初期化以外の用途はコンストラクタ内でのメンバへの(一見)代入(に見える構文)で十分なのでわ!?
というのが漏れのスタンス まあ漏れの案の欠陥としては、
コンストラクタ内でthisを他の関数bar()(すでにコンパイル済みかもしれない)に渡して
barの中でthis->m_aに代入するのはどうなんじゃ、というのはあるが
(C#はこの点現行C++と同じ実行時コストを支払っているハズ…
つまりデフォルトコンストラクタでFoo::m_aを構築した状態でコンストラクタに入る >>443
> 基底クラスとconstメンバの初期化以外の用途はコンストラクタ内でのメンバへの(一見)代入(に見える構文)で十分なのでわ!?
お前がそう思うのは勝手だが、わざわざ用途毎に構文を分けるのは悪手だろ
って言うだけのこと スマン>>444の末尾2行は抹消
C#はオブジェクトを参照型でしか扱わないから、明示的にFoo::m_aに対して
どっかで明治t系にnew T()を書かねば何も起きないから、書かなかった場合の実行時コストも糞も無い いやすまん>>442の方針にはまだ欠陥があったわ;
Foo::Foo() {
m_a = 1; // (1)
m_a = 2; // (2)
}
と書いた場合、(1)は>>442の方針でm_aの初期化とみなすことはできるが(2)をどう解釈すべきか曖昧になる
やっぱメンバの初期化はコンストラクタ本体実行前に1回だけ行われるようにする現行メンバ初期化構文の方がスマートじゃわ;;
というわけで完全に自己解決しますた! 黎明期からROMやっててUNIX板の騒動を解決した御仁もいるんだろ >>361
<<を使ったフォーマットだと語順を簡単に変えられなくて翻訳対応しづらいという問題もある。 なんか、相談室じゃなく、テクニックを披露し合って
自慢ごっこスレになってるな。
初心者は入れないし、もし書いたら、さげすむばかりだし。
本当に自慢ごっこスレだな。
おまえらだって、最初はなんにも知らなかった・わからなかったのに。
ちょっとわかる様になったら、自慢ごっこだな。
本当にわかっている人は、簡単な言語で良いソフトを作っているよ。
テクニック自慢ごっこはやめれ。 テクニックでもなんでもない
「c++知らない人の考えた正しいc++論」なんか要らんってだけ 煽れば答えを教えてくれると思ってるとでも思ってるのかねぇ。
まともな人はスルーするだけだし、テキトーに答える人がいてそれにかみつく人がいて荒れるいつもの流れ。 >>454
思ってるとでも思ってる→とでも思ってる
orz visual studio comunity 2015のc++で下記コンソールプログラムを実行すると
「0x73AD36A8 (tmmon.dll) で例外がスローされました (ConsoleApplication1.exe 内)
: 0xC0000005: 場所 0x0058F180 の読み取り中にアクセス違反が発生しました」
というエラーが出て停止するんだけど、原因が分かったら教えてください
ちなみに、コンパイル時にエラーは出ないし、プログラムも実行できるけど、プログラムの終了時にエラーが出ます
tmmon.dllというのはウィルスバスター関係のソフトらしいので、もしかしたらそちら側の不具合かもしれないけど
#include <iostream>
#include <conio.h>
using namespace std;
#define num 5000
class CLASS_A {
};
int main()
{
CLASS_A** ppa = new CLASS_A*[num];
for (int i = 0; i < num; i++)
ppa[i] = new CLASS_A;
for (int i = 0; i < num; i++)
delete ppa[i];
delete ppa;
cout << "hit any key!" << endl;
char ch = (char)_getch();
return 0;
} ステップ実行してどこで落ちてるか検証するべし。
これくらいのコードならおえるでしょ。 少なくともdelete ppa; はdelete[] ppa; じゃなくちゃダメだろ C++のクラスのコーディングをCで表現しようとするとどんなコードになる? structで関数ポインタ持たせるとかあるけど。
変換規定はない。 >>457
エラーが出るのが
return 0;
の後なので、ステップ実行してもよく分かりませんでした
>>458
なるほど、忘れてました
でも付けてもエラーは出るみたいです
トレンドマイクロの方に問い合わせしてみたほうがいいですかね? >>453
ほんこれ。
例の人のどこに初心者だから教えてくれという要素があったというのか。 >>460
賢い
関数ポインタに関数のアドレスを突っ込むタイミングは構造体初期化のタイミングだろうか? >>456
そのコンパイラのバグだろ。他の系でやってみたらいいと思う。問題ないはずだ。
自分の脳内コンパイラでもOKだ。 >>463
コンストラクタ関数を必ず持つようにするとかね。
Hoge h = constructHoge(...); >>456
>(tmmon.dll) で例外がスローされました
よくあること
Windowsだったらスタートメニューからメンテナンスツール(普通の管理画面ではない)を起動して
モジュールの全アンロードすると起こらなくなる >>464
エラーについて検索していたら、こちらのページにVisual studio 2017のdenev.exeと自作アプリの置いてあるフォルダを
ウィルスバスターの例外設定に追加して様子を見るようトレンドマイクロから回答されたという人がいたそうです。
私の場合は2015なので、とりあえず自作プログラムのフォルダを例外設定に追加したところエラーが出なくなりました。
なんか根本解決になっていないような気もするけど、とりあえずこれで様子を見てみます。
http://dxlib.o.oo7.jp/cgi/patiobbs/patio.cgi?mode=view&no=4148
ちなみに今気づいたのですが、エラーが出るのはVisual studio 2015のIDE上から実行したときだけで、
プログラム単体で実行したときはエラーは出ないようです。
回答してくださったみなさん、ありがとうございました >>466
ありがとうございます
>>467の方法でとりあえず解決しました #include <boost/pool/pool_alloc.hpp>
サンプルをテスト使用としたらTIのCCSにはこのあたりのライブラリがないんだが、このライブラリって
古いのだろうな?
boost::fast_pool_allocator<int> とかをテストしたいのだが、新しいライブラリはどれになるんだろうか? >>461
メモリリークだろ
メモリを解放せずに、アプリを終了してるとか? >>465
C++ならできるだろうけどCだとできる...? >>471
https://ideone.com/ZfcWrq
こういうイメージだな。
C久々に触ったわ。メモリ回りはおまじないが多いのでこわいよ〜。 >>472
どうしても記法を再現しようとするとそうなるだろうけど、
メモリを無駄にして割に合うのかっていうとだいぶん疑問ではあるよな。 >>473
まぁ、折衷案で関数群とデータで分けるとかね。
一応継承紛いなこともできなくないし。 記法を似せたいだけならともかく、関数ポインタを使うところはC++でいうところのvirtual functionでそれをクラスのIFとするのはC++でもめったにやらんわな。 COM(Component Object Model)はC++及びCでバイナリ互換のオブジェクトを作ることが出来る
vtblの配置は言語仕様上は定められていないが、MSがCOM(OLE2)を実装するにあたって定めた配置にしている処理系が殆どだ BisonでC語風の言語作ってるのですが、代入の構文が衝突してしまい困っています。
bison.yy: conflicts: 5 shift/reduce
*の回数を記録、Identifier = expression という構文を作りたいのですが、いい方法ありませんか?
*の検出はC語風のポインターを使うための処理です。
assignList :
assign {$$=new StatementAssignList($1);}
|assignList assign {$$=$1->add($2);}
;
assign :
Identifier '[' expression ']' "=" expression {$$=new StatementAssignVariable($1,$3,$6);} // 変数に代入:名前[式]=式;
| Identifier "=" expression {$$=new StatementAssignVariable($1, 0,$3);} // 変数に代入:名前=式;
| "*" {$$=new StatementAssignPtr();}
;
class StatementAssignList : public Statement{
public: std::vector<Statement *>m_list;
~StatementAssignList(){for(auto &p:m_list) delete p;}
StatementAssignList(Statement*pStatement){m_list.push_back(pStatement);}
StatementAssignList *add(Statement *pStatement){m_list.push_back(pStatement);return this;};
}
現在は、m_listで、StatementAssignPtr()の個数を調べてStatementAssignVariableの処理につなぐことを考えてます。 >>478
expressionがどうなってるのか知らないけどその文法だと
a=expr * a=expr * *
みたいに書けてしまうけど良いのか?
「左辺に書けるもの」を分けて整理すべし
C言語風ならC言語の文法を参考にしてもいいと思うけど アドバイスありがとうございます。
expressionは、 =禁止していますので、a = expr*a=expr * * は出来ないようにしてます。
手動で*の数を記述してみたのですが、conflicts: 3 shift/reduce となって混乱してます。
こんな感じ。。StatementAssignVariable()の第一引数を *の数にして実験。
statement :
Identifier "=" expression {$$=new StatementAssignVariable(0, 省略); }
| "*" Identifier "=" expression { $$= new StatementAssignVariable(1, 省略); }
| "*" "*" Identifier "=" expression { $$= new StatementAssignVariable(2, 省略); }
;
gcc 3はbisonのソース有ったので見たのですが、難解でしたorz
構文の設計ムズカシイ
conflicts: 3 shift/reduce無視しちゃっていいのかなぁ。。 > コンパイル時にエラーは出ないし、プログラムも実行できるけど、プログラムの終了時にエラー
スタック破壊の典型的な症状だな >>480
いや、assignListはassignの1以上の繰り返しで、assignは
identifier [ expression ] = expression
identifier = expression
*
のどれでも良いのだからassignListは
a=b * a=b * * a[b]=c *
みたいにassignを自由な順番で書けてしまうよね?
おそらくexpressionに2項の乗算が入ってるでしょ
それでセミコロンで区切らない文法とか?
a = b の次に*が来たときに乗算の右辺を待つ状態へshiftするか、それともa=bをreduceして次の代入文へ移るかが曖昧なのだと思う
常にshift(乗算優先)が望みなら無視してもいいけど、 a=b *c=d (代入二つ)とは書けなくなるかな >>481
あれから少し調べてみたけど、クラスを使わない、このプログラムでもエラーが出ることが分かりました
またnumの値によっても変わるみたいで、このプログラムの場合はnumを3805まで減らすとエラーが出なくなります
(昨日のプログラムの場合は、また別の値だったと思うけど)
エラーが出るのはIDE上で動かした場合だけで、プログラム単体で動かした場合はエラーが出ないからIDEの不具合なのかな?
マイクロソフトに報告するべき?
#include <iostream>
#include <conio.h>
using namespace std;
#define num 5000
int main()
{
int** ppa = new int*[num];
for (int i = 0; i < num; i++)
ppa[i] = new int;
for (int i = 0; i < num; i++)
delete ppa[i];
delete []ppa;
cout << "hit any key!" << endl;
char ch = (char)_getch();
return 0;
} >>483
すみません、再確認したらnumの数を減らせば出なくなるというのは間違いです
ただ、出にくくなっているような気はするけど >>482
再帰的下向きコンパイラ見たいな構造で、expressionに、乗算2つ入ってます。
%prec を排除して文法作ってましたが、曖昧な表現が衝突の原因っぽいですね。
文法修正してみます。ありがとうございました。
expression : term1 | expression "||" term1 {$$=省略;} ;
term1 : term2 | term1 "&&" term2 {$$=省略;};
省略 ...
term7 : term8 | term7 '+' term8 {$$=省略;}; term7 '-' term8 {$$=省略;};
term8 : factor
| term8 '*' factor {$$=省略;}
| term8 '/' factor {$$=省略;}
| term8 '%' factor {$$=省略;}
factor:
'-' factor {$$=省略} // -xxの時 NEGの処理
| '*' factor {$$=省略;} // *xxの時 ポインターの処理
| '(' expr '){ $$ = $2; } // ()
| func // 関数呼び出し
| value // 変数
| number { $$ = $1; }// 数値
; >>477
C++ 用の宣言と C 用の宣言がマクロで分岐するようになってるのを読んだことが有るんだけど、
C++ で引数を参照で渡してるやつが C ではポインタになってて、
それってバイナリレベルでは互換性があるんだ〜と思ったことがある。 >>483
_getchあやしくね?
cin.get(); に変えてみたら? >>483
試しにvs2015とvs2017で動かしてみたんですが、正常に動きますよ?デストラクタ確認でちゃんと動作してるみたいです。
ch = (char)_getch(); ってとこは書き換えて、getchar(); にしましたが。。
#include <iostream>
#include <conio.h>
using namespace std;
#define num 5000
void test1()
{
int ** ppa = new int *[num];
for (int i = 0; i < num; i++) { ppa[i] = new int; }
for (int i = 0; i < num; i++) delete ppa[i];
delete[]ppa;
cout << "hit any key!" << endl;
}
class MyInt { public:int n; MyInt(int i) :n(i) {}~MyInt() { printf("~MyInt %d\n", n); } };
void test2()
{
MyInt ** ppa = new MyInt *[num];
for (int i = 0; i < num; i++) { ppa[i] = new MyInt(i); }
for (int i = 0; i < num; i++) delete ppa[i];
delete[]ppa;
cout << "hit any key!" << endl;
}
int main(){
test1();test2(); //共に普通に動作確認済み
getchar();return 0;
} 伸び縮みしないんだったらunique_ptrで十分じゃん >>483
ウィルスバスターのdllでエラーならMSに言っても意味ないんじゃないか。
デバッガがアタッチされてるとウィルスバスターのdllがおかしなことして起きるってことじゃないの? ウイルスバスターが干渉しているっぽいなら
VirtualBoxでウイルスバスターのない仮想環境を作って
その中で動かしてみればええやん セキュリティソフトを動かしていたら、多くのアプリは、正常に動かない
多くのアプリの説明書に、そう書いてある >>487 cin.get(); とgetchar() もやってみたけど同じでした
>>488 ウィルスバスターはインストールされているでしょうか?
エラーを出すのがウィルスバスターなので、ウィルスバスターの入っている環境じゃないと出ないようです
>>489 vector使ってみたけど同じでした。今までvectorってあまり使ったことなかったけど、これからはvectorを使うことにしよう
int main()
{
vector< vector<int> > ppa;
ppa.resize(5000);
for (int i = 0; i < 5000; i++ )
ppa[i].resize(20);
cout << "hit any key!" << endl;
char ch = (char)_getch();
return 0;
}
>>490 実際のプログラムでは伸び縮みします
>>491 そうですね、ウィルスバスター側の問題かもしれない。トレンドマイクロに問い合わせしてみようかな?
>>492 ウィルスバスターを終了した状態ではエラーは出ないことは確認しています
ただ、visual studioとウィルスバスターのどちら側に問題があるかは分からないけれども
>>493 そうですね、でもウィルスバスターを止めるわけにもいかないので
とりあえず、プログラムを最後まで実行させなければ問題ないので、IDEから強制終了することで対応しようと思います。
プログラム単体で実行したときはエラーは出ないので 多くのアプリの説明書に、
「セキュリティソフトを動かしていたら、正常に動きません」
って書いてあるけど、何でだろ? セキュリティソフトは潜在バグを顕在化する事が往々にしてある 事情は知らんが開発中はウィルスバスター止めるとか>>467の方法で問題あるのか?
IDEから強制終了とかクソ面倒くさいことやってられんだろ OSの設定に干渉するようなモノはウイルス判定されることがあり得るでしょ。
それが善意かどうかなんて判定のしようがない。 >>499
ウイルス判定したならただクラッシュさせて放置じゃなくてアンチウイルスソフトとしての仕事しろよ。
ただウイルスバスターがクソなだけだろ。 ウイルスと判定したわけじゃなくて、判定するために干渉した結果としてそうなる場合がある。
コンソールアプリを起動しようとした場合に、一旦サンドボックス的なものの中で起動させてチェックして
直後にあらためて普通に起動するというのを見たことがある。
今回の場合、そのコンソールアプリを起動している VS の状況と噛み合わなくなっているのだと思う。
チェックのために何かしら介入しなきゃならないのはしょうがないのだが、
泥臭い、クソみてぇなことの塊なので、まじめに検証するのアホらしいぞ。 >>494
カスペルスキーの環境だと問題ないみたいですぜ。例外とかの設定もしてません。
バスターは入れてないです。 いまどきクライアントにはウィルス対策ソフトなんて入れないのが主流だと思ってたけど、
そうでもないのかな 上の現象見ただけでも信用ならんと分かりそうなものだがなあ。 Win10ならディフェンダーはいってるけど、前のOSとかなら入れるのか? ノートンのプロセスが勝手にこっちのdllを読み込んあとおかしな状態でアンロードしてアクセス違反おこしてノートンのプロセスがクラッシュするってのはあった。
アンチデバッキングなのかユーザーモードデバッガではアタッチできないからカーネルデバッガやるしかなくて原因見つけるのに結構苦労した。 Virtual Studioは素人が購入することは考えにくい専門的なソフトだからウイルスバスターのターゲット外なんだよ。
つまりさっさとどっちか捨てろってこった Visual Studioでアプリ作っててビルドしたてホヤホヤのプログラムをアヴィラ先生がウィルス認定しやがったのは過去に何度かあったわ >>456
delete[] ppa;
じゃないの >>498
>>467の方法は、エラーの発生を無視しているだけで、実際にはエラーが発生している可能性があるので
>>500
そんなスキルはないですw
>>503
ウィルスバスター側が悪さしている可能性もあるんですかね
せめてVisual Studioとウィルスバスターのどっちが悪いのかわかればいいんだけど
>511
>>483でdelete[] ppa;にしてみたけど、同じでした ウィルスバスターはエラー検出ツールじゃないし無視でいいよ
リソース関連のエラー検出したいならそれなりの検出ツール使うとか静的解析ツール使うとか ウィルスバスターミナルとかトーシローかよw
プログラムの仕組み知り尽くしていればまずウィルスなんかに引っ掛からないだろw 入力したコマンドを別関数に渡して結合してリターンして表示するってコードを作りたい
mainの中のusrとpassは実体もあるから受け渡し含めて問題ないと思うのだけど、
mainのcRetとgetcommandのcommandってどう定義するべきなのだろうか?
動くのは動くのだけど二つとも実体どこー?ってなってます
#include <stdio.h>
#include <stdlib.h>
GetCommand( const char* usr, const char* pass ){
char* command;
/** コマンド作成 **/
sprintf( command, "-u %s:%s", usr, pass );
return command;
}
int main( int argc, char* argv[] ){
char* cRet;
char usr[256] = {};
char pass[256] = {};
/** アカウント名の入力 **/
printf("usr Input : ");
scanf("%s", usr );
/** パスワードの入力 **/
printf("pass Input : ");
scanf("%s", pass );
cRet = GetCommand( usr, pass );
printf( "%s\n", cRet );
return 0;
} GetCommand関数のcommand変数をstaticなバッファーにするか、おとなしくstd::stringを使うか、GetCommandにバッファーへのポインターに渡すか。 >>517
このままのリターン形式だとstaticなバッファー作成しか方法ないってことですよね >>518
いや、malloc や、newもあり得る。だれが解放するかは問題だが。 考えてみるとバグの温床になりかねんね
単純に格納先の変数を用意して引数に渡すべきだとなった >>521
C言語ならな
C++なら>>517の言う通りおとなしくstd::string使えよ >>522
そやね
プロシージャとファンクションの考え方からファンクションにしたいのに
戻り値じゃないってのも変だ
string全然使ったことないけど使うことにする コマンドラインオプションで受渡した方がやりやすいような気もしないでもない。 こういう内容でstring使わないとか
超のつくマゾプレーだな sprintfは領域確保しないでしょ。こういうのがCは危ない。 >>513
たしかにウィルスバスターをエラー検出ツールとして使うのは、おかしいですね
>>467の方法でdevenv.exeが置いてあるIDEというフォルダと、自分のプログラムが置いてあるフォルダを
ウィルスバスターの例外処理に入れたら、気持ちが悪いぐらいにまともに動くようになりました
みなさん、ありがとうございました >516
1.間違い1
char* command; /** コマンド作成 **/
sprintf( command, "-u %s:%s", usr, pass );
ここが間違いで、sprintfを使う時には、かならず
char commad[256];
のように適当に多めにエリアを確保すること、256バイト確保しておけばメモリーをはみ出すことはまずない。
上の例ではcommandには何が入っているか不定だから、例えば0が入っていたら、メモリーの0番地に
usr,passを書き込んでしまう。だから普通はsprintを行った後で暴走する。
2.間違い2
char commad[256];
このように変更するとGetCommandは正常に動作するが、このcommandはスタックに確保されたメモリー
なのでGetCommandを終了すると、解放されて不定になる。したがってreturn command;はしては
いけない。
3.正しいやりかた
メモリエリアを確保して、それをGetCommnadに渡すのもありだが、引数が増えるので内部で確保してリターン
したいのであれば、memory確保する関数を用意してそこに書き込む。確保したエリアは使い終わったら
自動的に開放できる仕組みにしておく。
char *command = getarea(256); 256バイト確保しておけばメモリーをはみ出すことはまずない。とかw
文字列連結してるだけなんだから全部std::stringでやればいいだけだよ >>516
ていうかc言語初心者のところで聞けよ
その池沼レベルのソースコードだとここでは晒しものの血祭りになるだけだぞ >文字列連結してるだけなんだから全部std::stringでやればいいだけだよ
さてもしかりに
char commad[256000]; このくらい十分に確保できたらstringとどっちがあんぜんだろうか?
先ずはstringを使った方がいいと主張する理由を説明できないとな。
「やればいいだけだよ」って誰かがいってたから、という受け売りの信仰ではだめだな。 >>532
それでもstd::stringのが安全
根本的に考え方が古すぎる >>533
外部からの長さ無制限の文字列を受け付けるプログラムというのもセキュリティー上問題がある
バッファオーバーフローで即exploitされることは無いが時間をかければクラッシュを引き起こせる
というわけで長さ制限はどこかの時点で必須なのでassertionをOFFにしたsprintf_s()さいこー >>532
くだらなすぎて返す言葉もないです
すみません ていうかstd::stringにお任せしておけばデータサイズの管理が不要とか池沼の考え
何文字でも受け付けるとかいうのはテストしようが無いからまともな仕様ではない
よってまともな設計は不可能 常識的な範囲で受け入れてくれればよい。
それを行うことで何をしたいのかが見えないなぁ。 手前の常識がクライアントの常識と思い込むのは池沼のry つか>>537もかなり問題発言
スタックは関数を抜けたら開放されるのだから、
スタック領域を使い果たさないように設計された関数ならスタックをいくら使うかは関数の勝手
ここでも「スタックの消費は少ないほうが良い」という手前の常識が じゃあ、君はメモリが確保できないことをどう説明するんだい?
スタック大量に確保したら余計引っかかるぞ。 本質は同じ。瞬間メモリ使用量の問題だからな。
少ない方がイイに決まって無いかい? >>542
スレッド生成時にそのスレッドが使えるスタックは一般に割り当てが完了するから、
割り当てられた領域をオーバーしなければどう使っても良い
もちろんフルに使ってもヒープの圧迫にはならない
スタックが伸びれば伸びただけヒープ用メモリ領域を圧迫するとか
ごく一部の超ロースペックな組み込み環境(スタックがただ1本だけ=スレッドが1個だけ)限定の話じゃないの;
プログラムのメモリの使い方について一体どんな理解をしているのか;; >>544
じゃあnewしても問題なく確保できるじゃないか。
クライアントが不足の文字数ブッコンで落ちるよりはいいと思うけどね。
あと、ほかがヒープ食っててスタック確保できないケースはないの?
なんでもヒープにキックする人嫌い。 >>543
std::string経由でヒープ上にchar commad[256000];を確保する方が
スタック上にchar commad[256000];を確保するより常に優れた設計であるという根拠は? >>546
仕様が提示されてないから。250kbも使う保証がない。
なら、std::stringがchar command[256000]と確保するのは優れてるの?
折衷案なだけじゃない? >>545
藻前は文字数ブッコンでエラーを返すことと文字数ブッコンで落ちることの意味の違いの重大さがわかっていない
漏れは終始エラーを返すことを目指した発言をしてゐる >>548
あそー。
確保できなかたらSIZEは0になるから、ほとんどの処理は通らないようにエラー処理はできる。 >>547
なんか文字数の上限仕様が提示されたらスタック上に取るほうが良いと言ってねえが?まあ一般にそれで良いのだけども
>>549
メモリ不足チェックと文字数チェックを混同するのは池沼のry
メモリ不足はさまざまな要因が重なった結果起きる現象なので
「入力Xを与えたらメモリ不足でクラッシュする」という仕様はありえない
(入力とメモリ不足との関係は、一般に再現性のある形ではテスト仕様に組み込めない
一方、「文字数n未満の入力Xはエラーとする」という仕様ならアリで
再現性のあるテストケースも書けてバッファとしてとるべき配列サイズも計算できる(きちんと設計しているなら >>552訂正スマンorz
誤: 文字数n未満の入力Xはエラーとする
正: 文字数nを超過した入力Xはエラーとする >>552
ロースペックじゃないコンピュータつかってるんだろ?
非常識な文字数入れられたらはじくなんて別に難しくないだろ。
スペックわかってるんだったらなおさら。 スタックに充分な領域を確保したから大丈夫って頭おかしい設計だわ >>554
文字数チェック不要と考えているかもしれない>>530とかに言うべき はいはい。もういいわ。
エラー処理真面目にやるんだったら、そういう方向で考えるけど。
ここではそんなに求められてない。一般感覚が無いとそれ何回もやるのか?
不適当で有名な5chでなにを演説してるのやら。 >>555
やみくもにスタック消費量最小を目指すのは、
自分の関数がどれぐらいスタック使うのかおよびスタック領域にどれぐらい余裕があるのか
見積もる手間を惜しんで手抜きしているだけな可能性が微レ存、
ていうか「スタックに充分な領域を確保した」というのが真なら(机上検証、レビュー、テストで担保できたなら
「大丈夫」という結論で何の問題も無いんじゃ… >>544
スタック領域には当然上限があるが、常にその上限まで割り当てていたら無駄だろう。
LinuxもWindowsも必要に応じてページを割り当てる。 >>559
スタック領域を使い切るのが美徳とは言っていないわけでありまして、
なおかつページングの発生頻度は、メモリ消費箇所がスタックかヒープかの違いよりは
領域へのアクセス頻度の問題ではなかろうかと、 パフォーマンスの話じゃなくて、これが一般には正しくないって言ってるの。
>スレッド生成時にそのスレッドが使えるスタックは一般に割り当てが完了するから、
>割り当てられた領域をオーバーしなければどう使っても良い
>もちろんフルに使ってもヒープの圧迫にはならない んでchar commad[256000];をどうやってリターンするんだ? 普通ならstd::string使う
char使いたい人は使えばいい
おしまい > char commad[256000];
しかも0が非ascii >んでchar commad[256000];をどうやってリターンするんだ?
だからそれはstringでも同じだな。stringを使えばいいという発想では駄目ということだ。
メモリを確保する必要がある。
しかも、サブルーチンを抜けた後で、何処かでそれを解放する機構が必要だ。サブルーチンを抜けた
後だと自動で解放しない限りは解放する方法はない。つまり肝心なのは自動でメモリ解放機能が
ついていることだ。それがついてないstringクラスなんてこの場合は全く使い道がないってことだ。
だからstringって馬鹿の一つ覚えを言うやつは間違いってことだね。 >>569 std::string はデストラクタで自動でメモリ解放するよ。 auto f() {
struct { char a[256]; } r{};
return r;
}
int main (){ auto[array] = f(); }
ちょっとスタックが厳しそうだ >>569
本当のバカはその一つすらまともに知りませんでした 今どきstd::stringを批判してcharの配列の優位性を説くとか string_viewとか持ち出して言うならともかく >>575
全く批判になってないから。
string_viewも今回のような用途に使うもんじゃない テンプレートって基本ヘッダファイルに書くと思うけど、コンパイル単位ごとに全部コードのコピーが作成されるの? >>577
string_viewって何か知らないのか? >>578
規格は生成コードまで規定しないから、気になるならアセンブリとか見るのがいい。
関数テンプレートあたりだとコンパイル単位またいでも同じポインタが得られることが要求されていたりはする。 >>579
今回の件にstring_view使ってみなよ もしかして
string_viewとか(無理やり)持ち出して(バッファーを解放しないと)言うならともかく
という意味か?
そうだったらそこまでエスパーにはなれんかったわ >>583
何か勘違いしているか?
俺は生配列を使いたがるガイキチたちを擁護したいわけじゃないし
もちろん意見が一致していない
C++スレなのにC++のライブラリを食わず嫌いしてるフシのあるやつに
ちょっと話題を振ってみただけだ ストリングビューはストレージを保持しないぞ。
外部からやってきたやつに操作を与えるだけ。
パペットっていうかなんていうか。 std::stringは有用だがstd::XXXstream系は糞杉
→必然的にsptintf_s()とstd::stringを併用するスタイルになる
いずれワカル および有用だからといってプログラムの動作根拠を成す
数量的関係の把握をサボるというのは話が違う
std::stringにメモリが許す限りいくらでも長い文字列を格納できるから大丈夫とか、
スマポを使っとけばいつか(10万年後かもしれないが)確実に開放してくれるから大丈夫という見込みだけで
テストもせずに青天井なデータ処理を許すプログラムをリリースするのは
素人プログラミングに後退である
ていうか現在の潤沢なメモリ搭載環境では問題の発覚が遅れる分なお悪い どんなひどいプロジェクトで仕事すれば、こんなパラノイアを発症するんだろうな >>592
つーことは、おまえbad_allocをcatchせずに放置してるのか つか今気づいたが>>561は一体何が言いたいんじゃ…
ページ割り当ては論理アドレス上の領域確保に対し透過的なので
>スレッド生成時にそのスレッドが使えるスタックは一般に割り当てが完了するから、
>割り当てられた領域をオーバーしなければどう使っても良い
>もちろんフルに使ってもヒープの圧迫にはならない
の否定根拠にはなりえぬ >>595
ていうかむしろ藻前は正常系がbad_allocのcatchに依存した設計してるの? >>594
お前らがよってたかっていじめるからだろ w まだ516の糞コードの話題やってんのか
まったく飽きないフレンズどもだな
セルリアンに喰われちまえよ 次は20が控えててどんどん進化してるけどmeyers本なしについていける自信がないよ。
17以降遭難者が続出するんじゃなかろうか。 17ってそんなに難しいか?
14以後ってか11以後、03までのストイックを通り越したマゾプレーからの離脱が
大きなテーマになっていてautoのinitializer_listみたいなミスはしながらも
ちゃんとそれを正していく自浄作用が機能していると俺は思うが auto_ptrとかgetsとかトライグラフとかboolの++とか
危険で無駄で混乱を招くゴミが続々取り除かれてどんどん使いやすくなってるよね
生ポインタや生配列をいじくり回してメモリ壊すこともほとんどなくなった c++の機能がこのまま進歩していったとしてマクロは消えるかな? constexprとかautoのおかげでtemplateもマクロとして使いやすくなったよね。
そう考えるとテンプレートで出来なくてマクロじゃないと出来ないのって何かある? >>605
テンプレートとマクロの本質的な違いがわかってないな
スコープに従うテンプレートやconstと
ほとんど何も考えてないおまえみたいなマクロは
オブジェクト指向という観点からは全く別次元なものだ 「ほとんどなにも考えていない」とは手厳しいですね… 何だこの日本語wwww
オブジェクト指向たいして関係ないだろ マクロの乱用をさけるためにテンプレートが発達してきたんだからマクロ使わないでね >>606
文字列リテラルを、リテラルとして連結するのはマクロじゃないと無理じゃないかな。 >>614
不可能ではないと思うけど、そう気軽ではないというのは確かだと思う。 const char8_t[] u8hage = "hage"; // = u8"hage"
const char16_t[] u16hage = "ハゲ"; // = u"ハゲ"
const char32_t[] u32hage = "禿"; // = U"禿"
const wchar_t[] whage = "はげ"; // = L"はげ"
みたいなプレフィックス省略が出来ればいいのになって思うときがあるね >>616
Haskell だとリテラルは多相になっていて、型推論で適当な型にあてはめられるんだが……。
C++ では返却値だけ型が違う関数はオーバーロードできないルールがある。
その延長でリテラルは無引数の関数のようなものと考えると文字列リテラルが様々な型で有りうるようなのは難しいと思う。
型の情報が重複してるのがダサいと思うなら型名の方を auto で書くくらいかなぁ。 kotlinとかswiftにあるiterator.forEach{}の構文がc++にもついてほしい
c++だとiterator.for[=]{ }みたいな構文になるんだろうか >>615
うーん…
文字列リテラルは無理じゃね? >>619
コンパイル時定数という意味でのリテラルであれば出来るが templateだったら関数の返り値が異なってもokだしconstexprならコンパイル時定数だから変換さえ出来ればやれそうな気もする。
>>618
範囲for文は駄目? 自作クラスならtemplate関数で範囲forを閉じ込めるとか?
試して無いけどこんな感じで
class test{
//begin()とend(),++が定義されているものとする
template<typename Func>
void for_(Func func){
for(auto& it: *this){
func(lt);
}
}
} そういう臭い書き方はC++ではあまり採用されない方針
オブジェクト指向じたい、もうあまり言われてなくて
テンプレートによるメタプログラミングが主体になってる
オブジェクト指向を前面に押し出した言語はオワコンになるという法則があって
なもんで、魔除け、キチガイ除けの意味も含めて
Java や C# や C++ など、主流言語は
「マルチパラダイム言語」、「オブジェクト指向をサポート」
といった、ちょっと距離を置いた付き合いかたをしてるね
きっと、「全ての手続きは必ずただ一つのオブジェクトに紐づかなくてはならない」
という強迫観念的ともいえる窮屈な考え方が脳や精神に良くなかったのだろう
本当に精神疾患を引き起こしてリタイアする人多いし 変数forならラッパ作れば終わりだけどなんかつまらないね。
apply(op).for(sequence)とかのほうがインターフェースとしては見栄えがいいかも >>624
ユニファイドコールシンタックスっていう提案が出ていたけど、ぽしゃった。
俺もほしい。 「制御構造までオブジェクトに属するべき」ってやり過ぎというより単に根拠のない主張だよね。 range-based forで十分じゃん何が不満なんだ理解できない
俺が思うのはインデックス取れたらいいなあということぐらい >>630
最終的な結果がその処理順序に影響する(ここのオブジェクトへの操作が独立していない)場合には範囲for文使うなってことじゃね?
標準で取れるようにしてる言語も中にはあるけど >>601
meyers本ってそんなに役立つかねぇ
最初のeffective c++ちょろっと読んだ程度なので最近のは知らんけど
あの人の本に従ってる人は、自分で考えて創意工夫しない人が多いよ
セオリーに固執する日本人はそういうパターンに陥りがち お前らの創意工夫よりメイヤーズの方が100倍信じられるから 自分の才能や経験の不足を虎の威で補おうとしてるのなら、終わってるよ
meyersが「こうしろ」と言ってることの、理由まで含めて納得するならいいけど
そうでない人の方が圧倒的に多いからなぁ
>>636がまともな実力持ってるなら、meyersが言うセオリーに当てはまらない場面なんて山ほど経験してるはずだが >>635
あーいう本は典型的・基本的な工夫を示すもので、それを踏まえてその先へ行くもんなんだよな。
基本でしかないことに拘泥するのは下策でも、基本的なことすらおさえずにいるのは論外だから役には立つよ。
ある程度の経験を積んでいればああいう本に書かれているようなことは習得していて当たり前だっていう意味で
有用さに疑問を持つって意味かな? ド素人の創意工夫とかマジ勘弁してほしいな
セオリーもちょろっとしか知らないのに自分のコードが正しいと思い込んじゃうパターンだなこれは >>637 >>639
手元にないので軽くぐぐってみたけど、確かに初心者が手元に置いておくべき良書だというのは否定できないw
ほとんど突っ込みどころなんて無いし(当たり前の内容も含めて、”大抵のパターンで”正しい話ばかりだと思う)、
ちょっとけなしすぎたかも
ただ「値を返す関数の戻り値にもconstつけよう」ってのは理解できんかったがw(古い本なのでしゃーないか?)
こういうのあるから鵜呑みは良くないと思うんだよね
結局は自分の頭で考えないといかん
まぁ最新の版だと変わってるかもしれんし本文がどう書かれてるかわからないので、間違ってたらスマソ 俺のつたない経験でも>>637は口先だけの使えない奴だとわかる >>643
そっくりそのまま返すわ、どうせ教えられた通りの書き方しか出来ない無能だろ? >>642
呆れた。
ろくに読まずになおも否定したいのか。 >>640
おかしな事を言うね
ど素人は好きに創意工夫すればいいんだし、そもそも自由だろ
プロはプロなりのレベルで創意工夫してるんだろうし、対象層がわからん >>645
だいぶ昔に借りて読んだ程度のうろ覚えで否定したが
>こういうのあるから鵜呑みは良くないと思うんだよね
meyers本に限らず、これが間違ってると思ってんの?
それとも
>「値を返す関数の戻り値にもconstつけよう」
これが正しいと思ってんの? >>647
発言を局所的に切り取ってやり玉に上げるマスゴミみたいなやつだな。
否定したいならちゃんと読んでからにしろよ。
それに世界中のc++erに査読されて正誤表も常に更新されている本に>>647が突っ込めるようなことは書いてないから。
後、c++11以降はmodern effectiveのほうだから間違えないようにね。 >>637が正しいなら「meyersが言うセオリーに当てはまらない場面」で使うべきセオリーを解説した書籍があって然るべきだが
そのセオリーを持っているのは世界中で>>637一人だけらしい >それに世界中のc++erに査読されて正誤表も常に更新されている本に>>647が突っ込めるようなことは書いてないから。
それ言い出すとmeyers本以外もそうだよね
>自分の才能や経験の不足を虎の威で補おうとしてる
と言ったのがよっぽど図星だったのか?
>「meyersが言うセオリーに当てはまらない場面」で使うべきセオリーを解説した書籍があって然るべき
何言ってんだこいつ・・・・ 上級者ぶったド素人が煽ってくることが最近多いんだよな・・・・沸かせてしまったようでスマン > 上級者ぶったド素人
笑うところなんだろうか... 何の役にも立たないことしか言えないマウンティング野郎なんて放って置けよ
俺も最近C++使う頻度が落ちてきてるので最新の規格について行くのがつらい
おすすめの本を紹介してくれよ あ、一つ看過できない文があったので突っ込んどく
>>650
>発言を局所的に切り取ってやり玉に上げるマスゴミみたいなやつだな。
>>647で切り取ったのは全て俺のレスなんだが・・・バカじゃないの >>646
プロであるということとド素人であるということが両立することもあるのが業界の闇ってやつだ。 プロってプロフェッショナルの略なんでしょう?
意味は専門家、本職
素人とは
その事に経験が浅く、未熟な人。
その道で必要な技能や知識をもっていない人。ま
た、その事を職業・専門としていない人。
両立はかなり困難。
プロになりすます素人なら有るかもしれないが、ちょっと意味が違うよね。 両立つーかさ、誤解されるんだよね
俺も時々ご近所のオバチャンに
パソコンのプロなんだと勘違いされる
俺はPCに関しては完全にお客さんなんだが >>659
その道で生計たててるド素人ってことだろ 人に教示して何らかの成果を与えられるレベルの人間を人はその道のプロと呼ぶ >>546
これって皆さんどう考えてますか?
うちのプロジェクトでは規約で
スタック領域は基本16KB未満、
例外で許容出来るのは1.8MBまで、
オートは厳禁と決まっているので
気にしたことなかったです >>664
>オートは厳禁
こっちの方が気になるんだが >>665
auto変数じゃないです
allocaのことです >>667=>>626
あんなアホな長文書けるやつに無能とか言われたくないわw
今はメタプログラミングが主流かーそうかー
あと、かつてオブジェクト指向を最も全面に押し出してたのがJavaだったんだけどね
ついでに>>650=>>657
ID変えてまでご苦労さん >>664
組み込みなら別に珍しくない
ってか関数単位の制限なら結構緩いと思う 言うなれば、そうだね
いい年越えたおっさんが、子供を笑ってるのがあまりに滑稽だったから
逆に笑いものにされてる、と言ったところか
あと、自分の発言の都合の良い部分だけ切り抜いて押し通そうとする幼稚な戦法が
通じると思っているあたり、随分な思い上がりだな ああ
> 都合の良い部分だけ切り抜いて押し通そうとする幼稚な戦法
は君の言う「自分で考えて創意工夫」の結果なのかな?
こーゆーのが透けて見えるから愚者と言われるんだろうな
気を付けたほうが良いよ >いい年越えた
こいた、な
メタプログラミングが主流、の説明してもらえる?
出来ないのなら、煽るしか能のない荒らしだと自覚した方がいいよ
C以来のテクニックやC++でのOOPなどの昔ながらの技術はもう出尽くしてるから
そういう誤解する初心者が多いんだろうけど・・・・まともにメタプログラミングやったことあれば
それが主流だなどと豪語できないよ それは君が文章やスレの流れを全く読めないというだけ
> メタプログラミングが主流、の説明してもらえる?
まさに一部だけ抜き出してマスコミ云々だな
それで一部だけ抜き出して自分のフィールドに持ってきて
ゴチャゴチャ言うのが君の創意工夫なのか?通用しねーよ
>C以来のテクニックやC++でのOOPなどの昔ながらの技術はもう出尽くしてるから
>そういう誤解する初心者が多いんだろうけど・・・・
>まともにメタプログラミングやったことあれば
>それが主流だなどと豪語できないよ
↑全体的に攻撃先がズレてて的外れ
>>618を読めば分かるが、「次期」C++に入ってほしい、というような内容
で、OOにこれ以上施すことはあまりないので、C++標準化委員は
OOよりメタプログラミングを主体に策定している
(から、今更OOっぽい書き方は入らないんじゃね?)と言ってるまで ああ、そういう流れだったか、そこは誤解してたようだスマン
ただし>>626の4行目以降、全部お前の願望だと思うがw
>まさに一部だけ抜き出してマスコミ云々だな
>それで一部だけ抜き出して自分のフィールドに持ってきて
>ゴチャゴチャ言うのが君の創意工夫なのか?通用しねーよ
うん、しつこいよ
というか>>656でその煽りが不適当だと指摘してるんだが本人謝りもしねーし
そういう悪意ある煽り文(しかも他人の文に乗っかって)を自分で読んでどう思う?
俺がこういうキツイ書き方してる相手は全部煽ってきた相手だけなんだが
>C++標準化委員はOOよりメタプログラミングを主体に策定している
11, 14, 17, 20の新機能見ても、そうは思えない
自分の願望をさも事実かのように書くのはいかんよ
>>618的な書き方が入ると思う、というわけではないけど 自分の発言だろうが、他人の発言だろうが
都合のいいところだけを切り取って流れを無視するのは
マスゴミ的って話だろ、そういう余計で姑息な工夫は要らないし
その意味で「お前の創意工夫は要らない」って笑われてるんだろ
誘導尋問じゃねーんだよ
> >C++標準化委員はOOよりメタプログラミングを主体に策定している
> 11, 14, 17, 20の新機能見ても、そうは思えない
あ、っそ 新機能の話をしていると初心者はさもそれが当たり前に使えなければならないように感じるがそんなことはない。
俺C++でクラスを自作することかなり少ないし。関数だけでもプログラミングはできる。
constexprも入ってやりやすくなったしな。そしてそれを全部内包するのがC++だ。 朱に交われば赤くなるって諺もあるしなぁ
初めからウンコを触るつもりで取り扱ってないと危険なのかも
思考が染まると、それを通して周りを見るので
ヒントが沢山あっても正しく捉えられなくて
なかなか抜け出せないのかもしれない
それか、初めから頭がおかしかったパターンもあるかも
どっぷりな人はそっちかも
黎明期は集団で流れることがあるからなぁ (なにせ悪は甘美)
学生運動とかいう今考えると理解しがたいのが流行ったり
大人側が組み入れながら徐々に脱却って感じかね >>676
うわ、話にならんわこいつ・・・
>>677
荒れさせておいて同意するのも申し訳ないけど、俺もそうとしか思えない
D&E読んでも、C++がマルチパラダイムを自称するのはそういうことだし
「知らないことがその人を不幸にしない」とかゼロオーバーヘッドの話はまさに>>677に合致する
最近C++を勘違いしてるヤツがデカイ口叩きすぎだわ
そういうのはごく一部で、大抵無視されてるんだろうけど、C++を学ぼうという初心者が減ったら迷惑なんだけどな・・・・
荒れさせてスマソ、バカが調子に乗ってるのでこの辺にしとく C++ってクラスとかテンプレート使うのがパチッとくる
場合はいいけれど、難しいで。
過去のCのプログラムとかC++のクラス使って書き直そうとすると。
実力なしでゴメソ。 OOに関してはひところ純粋主義者が極端な言説を展開してC++をdisる流れがあったから、
それに対する反発と恨みがあるんだろうよ >>681
俺もC++でOOのなんたるか理解しようとして心が折れそうになった。
肩身せまそうにbetter Cとしか使ってませんとか。
今ならrubyとか極端な話、powershellのコマンドいじくって
た方がわかりやすい。隠ぺいか(カプセル化)も
中身が細かく知りたいときには、イーッってなるし。 なんだかんだ、OOはオプションのうちの一つ
というありきたりの結論 >>682
カプセル化は、アクセス・窓口を制限・整理する、という目的だとおもいます
>>677
>新機能の話をしていると初心者はさもそれが当たり前に使えなければならないように感じるがそんなことはない。
じゃ、ムーブセマンティクスも忘れちゃっていいですか、RVO に頼るだけでいいですか?え?だめ?やっぱりやらなきゃだめですか >>684
最適化するんなら必須か知らんけど、あるていどはコンパイラさんに投げてもよいのでは? もうなんの話をしてるのかよくわからんけど
>>637
> >>636がまともな実力持ってるなら、meyersが言うセオリーに当てはまらない場面なんて山ほど経験してるはずだが
の具体的な場面だけは教えて欲しいわ >>684
>カプセル化は、アクセス・窓口を制限・整理する、という目的だとおもいます
(データ+アクセス専用関数)=クラスだろ OO用語の定義に関して、何か始まりそうな感じだが
もう何十回と繰り返されたか、初心者的にはまだまだやり足りないのかもしれないが
老婆心ながら言わせていただくと、OO用語の定義談義合戦は過去幾度となく繰り返されたが
特に意味はなかったから止めておいたほうが良いよ
OO自体、まじめに考えてもあんま意味ないっつーか、むしろまじめに考えるとドツボっつーか
一見正しいけど、本質的には意味が無いことってあるじゃん
ある視点で見れば正しいんだろうけど、そういうことじゃないっていう
どうしてもやりたいなら止めないけど 定義がないんだから議論の正しさの検証も測定もできないしね 測定機ならAliexpressでいろいろ売ってるよ。 C++のクラスなんて便利な構造体以上の何者でもない
OO宗教でそれ以上の縛りを入れる必要なんてないわ C++の書式がどーの新機能がどーのってプログラマーが、楽になる機能なわけで、本質は、楽してコードが動けばいい。
学術的だとどーでもいい。議論するだけ無駄。
コンパイラは、速くて、安全なアセンブリコードを吐いてくれればいいよ。 禿もそういう系の揉め方を防ぐように気を使っているらしいな
なんだっけ、どの分野の人々をも侮辱しないとか
全てが1つのクラスから派生しなければならないというのは押しつけがましいとか ??数値の比較をしていってある一定の差があるところを区切っていきたいです
たとえば{1,4,7,8,11}って値を先頭から見て行って差が2以上あるところ{1}{4}{7,8}{11}のような感じで区切る
どうすれば実現できるでしょうか >>694
「区切る」の定義をしてくれ
入力が文字列じゃなくて数値ってことは、間に区切り文字を挟むとかそういうことじゃないんだろう。 後ろから前を引いて2以下?なら前を前回と同じバッファにプッシュバック。的な感じ。 >>695
後々区切られたまとまり毎に操作したいので
できればまとまり毎にそれぞれ別の変数に入れたいです
ただ操作上絶対に有り得ない数値を区切り文字として使うのでも良いです
{1}{9999}{4}{9999}{7,8}{9999}{11}{9999}
みたいな形で >>694 の書き出し化けてない?
「??白lの比較をしていって…」と表示されるんだけど。
対象の {1,4,7,8,11} はconstの整数のvectorへの参照で受け取るとして、
結果は要素グループごとに格納したvectorのvectorで返すかな。
各グループの先頭要素へのインデクスを格納したvectorで返すかも。
>>697 を見ると、前者の方が後の使い勝手が良いのかな。
要素グループのvectorのvectorってこと。 >>699
実装も前者の方が楽そうですな。
前の値と比べて差が広かったらグループ追加。 >>699
その部分は数値の比較と書きました
要素グループのvectorのvectorですか
どのような感じで書けばいいとかどのような調べかたをすれば良いか教えて頂けないでしょうか
取っ掛かりが分からなくて >>697
参考までに聞きたいんだが
この処理を何に使うの? >>704
ある方法で手に入れたいくつかの数値を先頭値から見ていき、
前後で差が小さいもの同士でグループ分けしていったあと
そのグループ毎の平均値を出していきたいだけです こういう泥臭いのは人に聞くよりもスクリプトでもなんでも良いから書いて試行錯誤すればいいと思うのよ >>705
ruby2.2〜ならchunk_while/slice_whenで出来る >>705
思い付くまま書くとこうなるがもう少し短く出来そうな気もする
Ideone.com - dOQm10 - Online C++ Compiler & Debugging Tool
https://ideone.com/dOQm10 >>711
ありがとう参考にする
しかし、よくこうスラッとプログラム書けるよなぁ
凄いわ 自分なりにやってみた。
https://ideone.com/ugURi1
>>711
vector::insertで領域の再確保が起こると既存のイテレータが破壊されるんで
24-25行あたりの処理はヤバイ。 すれちがいだけど、
C++が出る前のC言語で、STLが必要な処理はどうしてたの? >>716
固定バッファとか、ヒープとか、自己参照構造体などで管理してたはず。 一応つっこみ。
型の一般化がテンプレートと思うが
マクロじゃなくてテンプレート使えって書いてた本もあったような
気がする。 >>716
STL 等はあれば便利なだけで「それが必要な処理」などない。 >>716
STLで使われているアルゴリズムはC++前からあったものばっかだよ 汎用アルゴリズムのコードを業界で共通化することもなく、みんなが各々で実装してたんですか?というアンチテーゼだろ まぁ、ライブラリとして偏在はしてたんだろうけど、あの会社はあのライブラリこの会社はこのライブラリってややこしいことになってたと思う。 リンクリストと平衡二分木ぐらいなら雑に書いても500行ぐらいでできる
みんな大学の復習と思って書いてたんじゃないかな? 自力で書いてる人の方が多かった
STLがあっても用途によっては独自になるよな
ディスク上に作るとか、JPEGのハフマン符号みたいに表現が決まってる物とか STLはあくまでお手軽用途
表現縛りがなかったとしても、
ガチガチに最適化する用途では使えない if ( オーバーヘッドがない != 最適化される ) 最近は凝ったアルゴリズムより単純な配列(vector)の方が速かったりするうえに、余程古いかクソな標準ライブラリを使用してない限りstd::vectorを最適化する余地なんてほぼ無いわな。 最適化はコンパイラに任せてソースは読み易さ重視
std使っとけばデバッガでも追いやすいし 拡張ライブラリが有ったとしたら、名前空間はstxになるのかね。 Qtでウェブサイト作ったら何の問題もなくずっと動き続けてびっくりですよ。
Javaスレの人たちがC++は稼働し続けるとメモリーの分断化で落ちるとか言ってたから、
早く書き直さなきゃって思ってたんだけど。
クライアント用のQtがサーバーで頑健だったのは意外だった。 >>741
クソJavaプログラマーがC++を書くとほぼ間違いなくやるただのメモリリークを俺のせいじゃないということにしたかっただけというのに1票 自分のコードでさえ後で読むと読みやすく書いたつもりが裏目に出ていたりする 俺も最近unique_ptrに任せっきりでdeleteってほとんど書かねえわ
コピコンの=deleteとかは書くけど >>739
古いコンパイラ(つっても10年くらい)だと、クラス内の配列をイジるとクラスオブジェクト自体がイジられたことになるので最適化放棄とかしてたしなー
そういうのだとvectorなんて最適化放棄しまくり。 >>748
オブジェクトXに対するアクセスの最適化放棄はコンパイラの知りえない形での
Xへの副作用が有り得ると判断された場合に行われるがこれは現用コンパイラでも変わらん
改善したというのはコンパイラの能力向上というよりは、テンプレートによるインライン展開のご利益なのでは…
(つまりstd::vectorは元来最適化向きの進化である 例:
次のコードの並びにおいて、
1と3の読み込み結果は同一とはみなされず、1〜3を通してのX.aのレジスタ割り当ては行われない
1. Xのメンバaを読む
2. 外部リンケージ(かつ素性の知れた組み込み関数以外)の関数foo()を呼ぶ
3. Xのメンバaを読む
特効薬はfoo()のインライン展開 なお手動を厭わないなら次の風にしても良い:
0. auto変数v = X.a
1. X.aを読む代りにvを読む
2. 外部リンケージ(かつ素性の知れた組み込み関数以外)の関数foo()を呼ぶ
3. X.aを読む代りにvを読む
これならいくら古いコンパイラでもvを1〜3を通してレジスタ割り当てすることが気体できる 浮動小数点をすべて網羅するループが書きたいのですがどうすればいいでしょうか。 http://takashiijiri.com/study/miscs/fastsqrt.html
やりたいことは、上のサイトにある高速根号計算の精度検証です。
サイト内では2の根号に対して精度検証していますが
すべての倍精度実数に対して検証をしたいと考えています。
64bitの整数のビット表現を、同じビット表現の倍精度実数に変換できれば
整数についてループを回すことで網羅できると考えています。
変換の方法をご存知の方がいれば教えて頂けないでしょうか。 >>757
reinterpret_castでいい予感。 >>755
ところでその検証、何年ぐらい時間かけていい話なの? >>759
未定義動作でも「いい」と言うなら、そう。 みなさま、レスありがとうございます。
>>757
memcpyでできそうです。ありがとうございます。
int main() {
double f = 0;
for (unsigned long long i = 0; i <= -1; ++i) {
void* fp = static_cast<void*>(&f);
void* ip = static_cast<void*>(&i);
std::memcpy(fp, ip, sizeof(i));
std::cout << f << std::endl;
}
system("pause");
}
>>760
そんなに時間かかるんですかね。。。
1週間ぐらいは覚悟してたんですが。
とりあえず回してみます。 >>763
https://randomascii.wordpress.com/2014/01/27/theres-only-four-billion-floatsso-test-them-all/
> ... you can test every float bit-pattern (all four billion!) in about ninety seconds. ...
32bit が 90 秒ほどで済ませられるそうな。 64bit だと単純計算で・・・ 735439.6... 年ぐらいかな。
1週間で済ませようと思ったら 38347922 並列ぐらいで走らせればよさそう。
検証する計算内容によっても変わるだろうけど、まぁがんばれ。 とりあえず範囲を絞って回してみて、
力任せの方法で受け入れられる処理時間なら単純なプログラムのまま、
時間かかりすぎるようなら先にプログラムを洗練させる、としないと。 >>764
ありがとうございます。
32bitと64bitが桁違いですね
範囲を絞ったり、間隔あけてサンプリングしたりしてみます。 isnan()でnanチェック入れたほうが良さそう >>761
未定義にはならなくね?ポインタtoポインタだからそのまま、で終わりでは。
なお、Cなら
*(long long*)&f = i; // mov命令でコピー
または
f = *(double*)&i; // fmov命令でコピー
>>766
まず仮数部53bit+指数部の偶奇で54bit分でいい。
非正規化数もいらないだろうから仮数部52bit扱いでもいい。
意味が分からないのなら仕様読め>>758 >>768
type-based aliasing rule (strict aliasing rule) というものがあってな。
(詳しく調べると闇に落ちるから言語オタクでもなければ深堀りはおすすめしない。)
mempcy なら動作が定義されてるかというとそうでもないんで、
明示的に未定義といわれているかどうか(=最適化で問題を起こしやすいかどうか)の違いしかないんだけど。 なんか古い書き方だから2000年ごろからの年季の入ったソースかと思ったら最近の奴なんだな >>774
古臭い技術専門が時代遅れのために作っているもんだから、古いと言われても仕方ない。
auto、C++11が使えるclang++に移行したい。 >>769
調べたけどこれでいいのか?
https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule
これならreinterpret_cast関係ないじゃん。static_castにしたところで変わらん。
ただそれ以前に該当しないだろ。
「同一のメモリを違う型としてaliasしたときにコンパイラがそれに気づけず最適化で削除してしまう」という問題であり、
今回はそうではない。
> mempcy なら動作が定義されてるかというとそうでもないんで
ほんとか?それじゃmemcpyマトモに使えないじゃん。
void*は++で1増えるって仕様に決まったはずで、、、と思ったがこれがgcc拡張だという話があり、このことを言っているのか?
ならグダグダ言わずにCキャストで書けよもう、としか思わないが。
或いはC++的には許せないのかもしれんが static_cast<double>にしてしまうとかか? すまんミスった
× static_cast<double>
○ static_cast<double*> >>776
static_cast じゃコンパイル通らない。
"*(long long*)&f = i" は double 型のオブジェクトに long long 型の参照を通してアクセスしているので
未定義動作になる。結果は「最適化で削除してしまう」に限らず、何でもアリだよ。
これが「「同一のメモリを違う型としてalias」に該当しないという理屈も無いでしょ。
memcpy の結果が定義されてるのは、同じ型のオブジェクト間でのコピーだけだったかと。
違う型の間で memcpy した結果の値が実は定義されてるということなら実に興味深いので
ぜひ規格の該当箇所を示して欲しい。
この場合の C スタイルキャストの動作は reinterpret_cast に丸投げされるだけなので話は変わらないよ。 ここまでnextafter/nexttowardが出てきていない >>778
> "*(long long*)&f = i" は double 型のオブジェクトに long long 型の参照を通してアクセスしているので
してないぞ。
それは「fのアドレスを(long long*)にキャスト(この時点でlong long*型)したアドレスに対しiを書き込め」
であって、つまり long long に long long を書いている。だからmovが出る。
逆に f = *(double*)&i; は double に double を書くから fmov が出る。
その後の最適化で変更されるのはまた別の話。
> static_cast じゃコンパイル通らない。
だったら最初から>>759の言うとおり、reinterpret_castでいいだろ。
> 違う型の間で memcpy した結果の値が実は定義されてる
void* と void* なんだから同じ型だろ。何言ってんだ?
お前、基本的に理解がずれてね? >>780
なるほど、オブジェクトの型と式の型との区別がついてないんだね。
そこの理解無しで aliasing rule に関する話は無理だから、
C++ の規格を読み直すなりして区別が付くようになってからの出直しをおすすめする。 >>781
俺には君が全く理解出来てないように見えるけどね。
まあ平行線だろうし、終わりでいいけど。 >>782
そうなると GCC も「全く理解出来てない」ことになるねぇ。
https://wandbox.org/permlink/WMFUTpXAgs2oZuos
> prog.cc:5:17: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
> *(long long*)&f = i;
> ^
> prog.cc:6:18: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
> f = *(double*)&i;
> ^ まあ未定義な動作がどこまで行っても未定義な動作であって(教条主義的には)悪なのは確かだが
>>784のリンク先のを読むと
>ストアによってPの値が変わる可能性を考慮しなくてはいけないからだ。
という理由で最適化できないケースがあるから考慮する代りに未定義動作ということにしますた!
というだけで、ストアによってPの値が変わらないなら特に問題を生じないように思える…
で、ストアによってPの値が変わるケースというのは
int main() {
P = (float*)&P; // このキャストによって zero_array の中で TBAA 違反となる
zero_array();
}
みたいな変態的なケースしかなさげ; >>784
答え書いてんじゃねーかよ。
> この種の未定義な振る舞いは、-fno-strict-aliasing フラグを指定することで無効にすることができ
つまり指定すれば万事解決だ。
ただその前にwarning出てても動作するとは思うが。
> この種の型の乱用はあまり一般的ではないので、標準委員会は、"妥当な" 型のキャストによる予期しない結果と引き換えに、大幅なパフォーマンス向上を選んだ。
これっていつから?LLVMに乗せた頃からっぽいが、、、日付や元URL見るかぎりC++11からか?
あとこれって、Cもか?
(Cでは俺が書いたようなキャストは常用されているから)
知っている人がいたらよろしく。 つかmemset(buf, ch, nのbufって__restrictじゃなかったのか…
今知った…… C89からずーっとそうだよ
お前が書いてるコードが動いてるのは、コンパイラがそうしないという保証を独自に与えているか(-fno-strict-aliasingはその一例)
さもなくばたまたま動いてるだけ >>786
広く知れ渡ったのは gcc 2.95 で実際にそのルールに基づく最適化が行われるようになってからかな。
https://www.gnu.org/software/gcc/gcc-2.95/features.html
> - Type based alias analysis is enabled by default. ...
そこから数えてももう 20 年近く経つわけだが。
知らずにそんなキャスト常用してるなら是非悔い改めてくれ。 (ま、__restrictな形でしかポインタしか使わない漏れには関係ないし… ちなみに-fno-strict-aliasing付けるとこんな基本的な最適化さえ出来なくなって
パフォーマンスが激悪化する可能性があるからな
それを完全に理解した上で万事解決だと言ってるならそれでもいいけどさ
int foo(double* pd){
int k = 42;
*pd = 666;
return k * 2;
}
-fno-strict-aliasingを付けた場合、戻り値を"84"に最適化することは出来ない
なぜならpdのアドレスが&kを指してるかもしれないから
(strict aliasing ruleが効いてればdouble*がintを指してたら未定義動作なのでケアする必要がなく最適化できる) >>791
引数で受け取った(有効な)ポインタが関数内のローカル変数を指すことは不可能だから、その例は最適化できるよ。 有効なポインタならね
デタラメなポインタがたまたま&kを指してるかもしれない
普通はそんなのは未定義動作だからケアしないんだけどそれをケアしろって言うのが-fno-strict-aliasing >>789
> mempcy なら動作が定義されてるかというとそうでもないんで (>>769)
これは間違いだろ。784内見る限り、
> Cは、このような型変換をmemcpyを使って実現することを要求している。
なら、memcpy使えば正しい結果が得られるはずだし、そうじゃないとコンパイラのバグになる。
つまり、>>763のコードは正しく動くはず、と読めるが。
ちなみに>>783のページで色々試してみた。(もし編集が残っているようならすまん)
全てgcc 7.2.0 で、結果は以下。
・CはC11/C11(GNU)の両方でwarinigも何もでない。
・C++はこの中の一番古いC++03/C++03(GNU)の両方でwarinigは出る。
ということはかなり昔からC++ではそうだった、ということだね。全く知らんかったわ。
ここら辺がCの連中がC++を嫌っているところなのかもしれない。
>>788
おお、サンクス、C++89からか。
俺環はVC++2008だからね。MS側が吸収してくれてるわけか。
>>789
いや俺環では問題ないしな。
つかたぶんこれC++の話で、上記試した限りCなら問題ないんだよ。
ただ俺はbetterCの人だから、まあ微妙なわけだが、、、VC++2017とかに移行するときは気をつけるよ。
さてそのリンク先
https://www.gnu.org/software/gcc/news/alias.html
も読んでみたが、つまり s->x_m[i] は s->a_m と型が違うから上書きしないはず、
だからループ内で毎回 s->a_m を取らずに前回の値をそのまま使っていい、ということらしい。(s->b_mも同様)
ただこれなら
for (unsigned long long i = 0; i <= -1; ++i) *(long long*)&f = i;
は確実に動くけどな。ここで端折られるのはfのアドレス確認 &f 部分だけだから。
ただしstackoverflowの連中は言っていることが少し違うから、もうちょっと確認が必要だが。 >>791
周回遅れですまんが俺には794に書いたとおり、
・型違いは全てmemcpy使え。
と読める。だから763のコードはOKだと。
>>791-793の内容は理解した。
さて再度だが、やはり以下は動くだろ。
for (unsigned long long i = 0; i <= -1; ++i) *(long long*)&f = i;
ここで問題なのは、「fがiのアドレスをさしてたら未定義動作(&f==&i等)」であって、
i をコピーしてやらない、ではない。
791-793の言い分どおりなら、これはwarningが出てるだけで全く問題なく動くはず。
ただしstackoverflowの連中はちょっと違うことを言っているが。 >>794
C の aliasing rule には memcpy, memmove によって宣言型を持たない(たとえば
malloc で確保した)オブジェクトの型 (effective type) を変更できるという規定がある。
引用された「memcpyを使って実現することを要求している」はこのことだろう。
でも、 C++ にはこれに相当する規定が無い。 >>796
残念、まだ理解できてないよ。
答えは >778 にある。
> "*(long long*)&f = i" は double 型のオブジェクトに long long 型の参照を通してアクセスしているので
> 未定義動作になる。結果は「最適化で削除してしまう」に限らず、何でもアリだよ。
これ以上は規格見てからしゃべってくれ。 てゆーか、見てなかったけど763はfor文回らねーじゃねーかよ!
>>798
ちょうどよかったので今>>795を改造してアセンブラ見てるんだが、、、すまんが今日は寝る。
昼前にはまた書くよ。 未定義動作マジコエー;;(>>784のリンク先の次のページ
ttp://blog-ja.intransient.info/2011/05/c-23.html プロセス屋さんががんばってCPUを3年ごとに倍早くしてくれるのだから
我々ソフト屋は口を開けて待っているだけにして
最適化なんてやめてしまえば良いのに
我々が忙しく働くということは、それだけバグを産むということなのだ…! >>795
出来ると主張する人に対して
たまたまできない一例を根拠に
出来ないことの立証を主張されても… CPUだけ速くなってもDRAMの速度が昔のままだ
.7CRなんて法則を持ち出すまでもなく
現実にCPU速度が飽和したと感じたことなどないはずだが >>795改造は-fno-strict-aliasing有り無しによらず動くコードが出た。詳細は以下。
https://godbolt.org/g/QaSwTn
-O3 -fno-strict-aliasing -std=c++14 -pedantic -Wall -Wextra で mov QWORD PTR [rsp+8], rbx (27,29行目)が出る。
-fno-strict-aliasing を切っても同じ mov 命令が出る。
だからこれはwarningが出ているだけで動くコードが出る。
このときのコードは以下。
void test() {
double f = 0;
for (long long i = 0; i <= 10; ++i) {
*(long long*)&f = i; // (A)
std::cout << f << std::endl; // (B)
}
} >>798
なお上記のGCC結果、或いは以下GCCのドキュメントは読んだ。
(ついでに後出の仕様書もチラ見したが、やはり今のところ君の理解がずれてるという見解だ。)
https://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Optimize-Options.html#index-fstrict_002daliasing-750
ここでは以下コードがアウトだと言っている。
union a_union {
int i;
double d;
};
int f() {
double d = 3.0; // (C)
return ((union a_union *) &d)->i; // (D)
}
アウトな理由だが、上記と794内URLによると、「『型違いのaliasはない』と仮定して最適化」する為であり、
つまり(C)はd名でdoubleに書き(D)はi名でint読み出しだから(C)と(D)は関係ない、
よって(C)はデッドコードでいきなり(D)の読み出ししてよし、ということらしい。
ただこれだとやはり上記(A)(B)は動く。(A)も(B)もfの読み書きであり、aliasして無いからだ。
この規定は「型違いの『aliasは』ないものとみなす」であり、aliasしてなければ関係ない。
今のところ見る限り、他の例も必ずalias(別名でアクセス)している。
なお正しくはunionを使え、ということらしい。>>763
まあ確かにunionはこれ用ではあるが、単発ならCキャストする奴が多いとは思う。
そもそもunionは撲滅対象だと思っていたのだが、これは意外だ。
(或いは仕様上 char*, unsigned char* については許可《どう見ても妥協だが》しているので、void*ではなくchar*にすればいい) 仕様書は以下でいいか?読み慣れてないからだいぶ推測が入るが、
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
俺の結論は以下かな。
・gccのは -fstrict-aliasing で、あくまで alias についてだが、仕様書内は alias なんて関係ない。
・fstrict-aliasing 出来る理由が3.10.10によるのなら、reinterpret_castの存在価値はなく、仕様書内に矛盾がある。
・おそらく reinterpret_cast 撲滅で union に書き換えろ、という方向か?
aliasってのは多分折衷案で、union 以外は全部アウトにしたいっぽい。
詳細は以下。
5.2.10 Reinterpret castでは特に妙なところはなし、型キャストは為される。
aliasについては3.10.10だが、reinterpret_castしてれば the dynamic type 扱いでアクセスに問題なし、と見る。
3.10.10.の注 54) The intent of this list is to specify those circumstances in which an object may or may not be aliased.
なんだから、やはりこれは alias されているかどうか?であって、アクセスできるかどうかではない。
ただしここを根拠に undefined behavior だから最適化してよし、としてるのはかなり強引で、
(というかここでalias云々がかなり唐突で、そもそもaliasの話をここではしていない)
(D)がreinterpret_cast扱いだというのなら仕様内に矛盾があることになる。
そしてこの解釈(=reinterpret_castされたものは the dynamic type ではなく undefied behaviorだからどうなってもよし)が通るのなら、
reinterpret_castの存在価値がなくなってしまうし、
aliasとかせこいことを言わず、reinterpret_cast相当のところは全部undefined扱いで削除していいことになる。
というか、多分コンパイラ側はこの主張で、これに対してユーザ側が反対し、
結果、 alias とかいう折衷案でごまかしているように読める。(既に書いたがaliasが唐突過ぎ)
確かに正しくはunionを使うべきであり、この流れだと将来的には reinterpret_cast は廃止で union しろってことになるのか?
しかし逆に言えば、C++89以来これで大して変わらないのなら、早々急に変わることもないか。 >>787
ポインタの引数が1つしかないのに__restrictつける意味ないからでしょ コンパイラがうまくType-Based Alias Analysis出来るケースをいくら列挙したところで
Type-Based Alias Analysisできないケースが簡単に生じることは否定できない事実じゃんヤバイじゃん?
unionの使用が解決策というのも語弊があって、unionのメンバのアドレスを取ってから関数foo()に渡す手順だと
foo()のコンパイル時には渡ってきた2つのポインタが、型が違うけど(ループ変数などの条件次第で)同じ領域を指す(ことがある)
かどうか(ループを実際に実行してみねば)判断つかないじゃん?→コンパイラは怖くてループをmemcpy()やmemset()に置き換えられない
つまりunionこそ別の翻訳単位に属する関数に下手な渡り方をするとaliasingのすくつと化す気配が微レ存
元を断つにはやっぱID:xhmNfS4m0やGCC様がおっしゃるように、
そもそも型の混同要因(つまりポインタのキャスト)を絶つか、最適化が効いてほしい関数でプログラマが明示的に__restrictするしか、
※ 個人の感想です >>808
> ただこれだとやはり上記(A)(B)は動く。(A)も(B)もfの読み書きであり、aliasして無いからだ。
どうも "alias" の有無を名前に基づいて考えてるみたいだけど、
C++ (ほか多くのプログラミング言語)の文脈ではソースコード中で使われる実際の名前は関係ないんだよ。
"*(long long*)&f = i;" は "auto p = (long long*)&f; *p = i;" と等価であり、
これらのうち名前をつけた後者だけがエイリアスの問題があるということはなく、
どちらも f が表すオブジェクトに対してエイリアスがある状態と言う。
(最適化器の気持ちになって考えればわかりやすいんじゃないかと思うんだけど・・・。)
3.10.10 の注が "alias" に言及しているのも、このルールが "aliasing rule" と
呼ばれるのもそういうこと。
> なお正しくはunionを使え、ということらしい。>>763
> まあ確かにunionはこれ用ではあるが、単発ならCキャストする奴が多いとは思う。
union で最後に書いたメンバと別のメンバを読み出すのも C++ では未定義動作だよ。
gcc は( -fstrict-aliasing の説明にもあるとおり)特別ルールを設けてある程度の保証を与えている状態。
https://gcc.gnu.org/bugs/#casting_and_optimization
> To fix the code above, you can use a union instead of a cast (note that this is a GCC extension which might not work with other compilers): >>809
> ・fstrict-aliasing 出来る理由が3.10.10によるのなら、reinterpret_castの存在価値はなく、仕様書内に矛盾がある。
元の型に戻せば元通り使えることが保証されているので、変更できない既存ライブラリの型に情報を無理やりねじ込んだりするのには使える。
3.10 の例外により unsigned char* などによるオブジェクト表現への直接アクセスにも使える。
> aliasについては3.10.10だが、reinterpret_castしてれば the dynamic type 扱いでアクセスに問題なし、と見る。
まだオブジェクトの型 (dynamic type) と式の型との区別がついてないようだねぇ。 >>810
memset()にわたるbufが__restrictでないポインタでないということは、関数の中で
memset(p, 0, 1000);
...
memset(p, 0, 1000);
と2回呼んだとき、pが非__restrictだったりグローバル変数だったりするとバカ正直に2回memset()されてしまう…
また、memset()は該当しないが
一般論としてポインタの引数が1つしかなくとも大域変数経由で(一見別のエリアを指すように見える)ポインタを受け取るケースがあるので
1引数関数でも__restrictが要るケースがあるんじゃわ; >>811
808のコードで言うとね、
union a_union {
int i;
double d;
};
int f() {
double d = 3.0; // (C)
return ((union a_union *) &d)->i; // (D)
}
がアウトで、
int f(a_union* u) {
u->d = 3.0; // (E)
return u->i; // (F)
}
にしろってことだよ多分。これは>>812内URL内容とも一致する。
>>812
と、ここまではいいとして、これもGCC拡張であり、
> union で最後に書いたメンバと別のメンバを読み出すのも C++ では未定義動作だよ。
これはマジなの?C++のunionのところを読めばいいのか?
> 最適化器の気持ちになって考えればわかりやすいんじゃないかと思うんだけど・・・
これの可能性も考えたんだが、これまで全ての例で必ず別名をつけられてる。
LLVMはあまり知らないが、LLVMにおいてはレジスタへの再代入は禁止のはずだから、
同じレジスタがずっと使われてて最適化器からも「同じだ」と見える可能性もあるよ。 ごめ>>814の前半は思い過ごしかorz
別にmemset()側に__restrictは要りませんな… >>813
3.10.10.4 a type that is the signed or unsigned type corresponding to the dynamic type of the object,
って言ってんだから基礎型も the dynamic type に含まれてると思うぞ。
> 変更できない既存ライブラリの型に情報を無理やりねじ込んだりするのには使える。
使えない。
reinterpret_castの結果がlvalueとして正当ではない、だからundefinedで何やってもおk、
というのが最適化していい根拠なんだろ。だったらreinterpret_castしたその値を使う時点で駄目だろ。
lvalueとして正当に使えると言うのなら、undefinedじゃないんだから最適化で削除しては駄目だ。
ただまあ、ここら辺を俺と君でやりあっても意味が無い。
おそらく20年前にガチで同じことが彼らによって既に為されているはず。
俺がコンパイラを作るわけでも無し、俺は現状確認だけでいいよ。 >>814>>816
>一般論としてポインタの引数が1つしかなくとも大域変数経由で
あ、そういうことか・・・
まぁmemset使ってそういう症状出るとしたら、呼び出し側のpでつければいいよね
自分は__restrictそんなに使い倒してないけど、C++の標準に入らないのかな >>817
これだけ言われてまだ dynamic type が何なのか読んでないとしか思えない発言が来るか。
https://timsong-cpp.github.io/cppwp/n4659/intro.defs#defns.dynamic.type
> reinterpret_castの結果がlvalueとして正当ではない、だからundefinedで何やってもおk、
> というのが最適化していい根拠なんだろ。だったらreinterpret_castしたその値を使う時点で駄目だろ。
ポインタの reinterpret_cast で型違いの結果を得ることは未定義動作にならないし、
それに * を適用して lvalue を得ることも未定義動作にはならない。
得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動作となる可能性がある。 >reinterpret_castの結果がlvalueとして正当ではない
えっ合法なんじゃ…
int x = 10;
char* p = reinterpret_cast<char*>(&x);
*p = 2; // *pがlvalueであるところの式
x = (int)*p; // 元の型へのキャストバック
printf("x=%d\n", x); // 2
多分最適化されると
printf("x=%d\n", 2);
になる >>812
> union で最後に書いたメンバと別のメンバを読み出すのも C++ では未定義動作だよ。
一応unionのところ(9.5)読んだ。これは書いてなかった。
ただしGCCが「独自拡張だ」って言ってんだからどこかにはあるのだとは思うが。
章番号分かればよろしく。まさか、書いて無いから未定義って奴か?
なお9.5.5ではanonymous union ってのが定義されてて、どうもこれでやれってことっぽい。
例は以下。
void f() {
union { int a; const char* p; };
a = 1;
p = "Jennifer";
} dynamic_typeはdynamic_cast<>とかtypeidの実装がvtableを悪用した黒魔術なので使わなーい
それはそうとして、Type-Based Alias Analysisの障害となるaliasingだけことさら問題視するLLVMの人らのスタンスはフェアではないキモス
同じ型でもaliasingは起こそうと思えばいくらでも起こせるし、コンパイラはプログラマーが意図的にaliasingさせるケースが有り得るのではと
猜疑心にとらわれて十分な最適化ができないのは同じ
やっぱC++は関数型プログラミング言語にシフトすべき頃合い >>819
3.10.10には the dynamic type と cv-qualified version of the dynamic type しかないのだが、
では double や long long は何型なのだ?
> 得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動作となる可能性がある。
ではその aliasing rule を読もう。何章だ?
なんとなく aliasing rule はコンパイラ側の仕様で、C++の仕様では無いと思うのだが。 >>823
なんでせっかくリンク貼られた定義を無視するの?(・・・英語まともに読めないならそう言ってね。)
dynamic type は式を評価した結果の属性であって型の分類ではない。
aliasing rule は basic.lval にあるルール "If a program attempts to access ... the behavior is undefined" を指す。
https://timsong-cpp.github.io/cppwp/n4659/basic.lval#8 >>822
違うぞ。
794内リンク読む限り、確かにこの最適化はフェアだし、使われていい。
というか、それ以前はポインタが一つでもあったら全く最適化が出来なくなっており、
確かにそれは問題視されてた。
だから標準化委員会がそっちを選んだ、というのは分かる話だ。
違う型でエイリアスすることはほぼないし。
問題は意図的にやりたいことが偶にあって、そのときにどう回避するかだよ。
763がこれに該当する。 >>826
現行の規格で保証される範囲でまともな方法を見出そうとしてるなら、苦労に見合う実りは得られないからやめとけと言っておく。
標準化委員会のおおかたもそんな認識だから bit_cast なんていう提案が好意的に進められている。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0476r1.html >>824
では最初から分かるようにそう言え。
こちらは仕様書を読むのが仕事ではないので、そもそも用語も知らない。見て分からなければそれまでの話だ。
つか、lvalue, rvalue もひどいが、 xvalue とかもでてきて、いよいよC++はどうしようもなくなりつつあるなと実感したよ。
Linusが嫌うわけだよこれは。
ただまあこれは本題でもない。 aliasing rule の確認の方が重要だ。
してそのリンク先、3.10.10と同じだ。
> 得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動作となる可能性がある。(>>819)
これはどこからそう取れるんだ?
reinterpret_castをした結果が正当なlvalueなら、それをデリファレンスした結果も正当なlvalueだろ。
この章にはどこにも”aliasしてる場合”なんて記述はない。
だらからここを根拠にするのがそもそもおかしいんだよ。
君が期待することがここに書いてあるとしたら、例えば以下になるべきなんだよ。
the dynamic type of the object IF THE OBJET IS NOT ALIASED,
とかね。でも実際はそうじゃない。 >>827
つか、完全に暴走してるなこれは。
これならmemcpyと同じだし、
わざわざ別に作らずともmemcpyを正式に認めてCと同じ並びにしたほうがいい。
それ以前に reinterpret_cast が使われている関数内は自動的に -fno-strict-aliasing すればいいだけなんだが。
(関数単位でこの最適化を切る。ほぼ全てこれでいけるはず)
ただまあ、これが真面目に議論されているのなら、仕様書の文面や俺の感想はともかく、
君の言う通り、今のC++の仕様では対処する方法がない、ということなのだろうね。 >>828
"If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined"
これが lvalue (それ自体は未定義ではない)を通した「アクセス」を未定義とするルールとして読めないのだとしたら、もうどう説明しても無理だろう。
用語を知らないといいながら共通の定義を求めるのではなく開き直って勝手な解釈に基づく話を進められるようではまともな会話にもならない。
説明は諦める。
規格や先人の解説を読みなおすなりして誤りに気づいてもらえれば幸いだ。
https://www.google.com/search?q=aliasing+rule >>830
ちげーよ。
俺は、reinterpret_castの結果が正当なlvalueなら、それはド頭の
the dynamic type of the object
に該当するから、
*(long long*)&f = i
はありだろ、と読んでるんだよ。そこは君も同じだろ。
> ポインタの reinterpret_cast で型違いの結果を得ることは未定義動作にならないし (>>819)
つまり (long long*)&f で long long* 型になるのはおk ←君の見解ね、俺も同意だが。
> それに * を適用して lvalue を得ることも未定義動作にはならない。
得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動 (>>819)
つまり、*(long long*)&f もおk ←これも君の見解ね、俺も同意で。
> 得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動作となる可能性がある
ここが違う。
3.10.10には alias が云々って何も書いてないだろ。
しかも *(long long*)&f = i; は両方とも long long なんだから、「型違い」のaliasではないんだよ。
だからGCC等の -fstrict-aliasing には該当しない。
というのが文面からとれる意味だ。あくまで「文面」な。
ただまあ、実際にはそうじゃないんだろ。 ああすまん、ちょっと慌ててて余分なコピペされてるわ。
上記1回目の「得られた lvalue を通したアクセスが…」は余分で。 >>830
> 俺は、reinterpret_castの結果が正当なlvalueなら、それはド頭の
> the dynamic type of the object
> に該当するから、
> *(long long*)&f = i
> はありだろ、と読んでるんだよ。そこは君も同じだろ。
違うねぇ。
オブジェクトの型 dynamic type は式の型とは違うし、式の型の影響を受けるものじゃないんだよ。
何度も区別しろと言ったつもりだったんだけど。 ごめん、アンカーミスった。 >833 は >831 宛てね。 >>825
確かに自分に中身のないやつほどルールブックを神格化するよな
自分なりにどう思うなんて怖くて言えないから
で、そういうお前さんは何か内容のある発言ができるのかね? > *(long long*)&f で long long* 型になるのはおk
んなこたーない
doubleオブジェクトの領域にlong longでアクセスすることが未定義動作 double f = 0;
と変数fを構築した時点で、「値0.0のdoubleオブジェクト」が作られてメモリに置かれるんだよ(規格で言うstored valueな)
それはスタック回収やdeleteで破壊されるまでずーーっとdoubleのままで、変わることはないの
外側でポインタや参照をどれだけいじくり回したって決して変わらないの
家の横に「←ここは馬小屋です」って看板を立てたって、その家は家のままだし、勝手に馬を入れて飼うのは未定義動作なんだよ
そろそろ理解したらどうなの >>835
内容ある発言と言われても別にこんなのは規格をひっくり返して議論するようなことでないし
たぶん俺なら(little endianだとして)
union Double {
double v;
struct {
uint64_t f:52; // fraction
uint64_t e:11; // exponent
uint64_t s:1; // sign
};
};
とかにするかな、それで何の問題も起こらない >>837
多分それが違うぞ。それはどこに書いてある?
少なくとも多くのCプログラマはそう思って無い。だから平気でキャストする。
そして830内ULRも読んだが、これも明示的なエイリアスがあるケースだ。
お前らが過度にびびって拡大解釈してるだけだろ。 あー、こいつcast-as-lvalueに完全に洗脳されている手合いかw >>839
https://timsong-cpp.github.io/cppwp/n4659/intro.object#1
> ... The properties of an object are determined when the object is created. ... An object has a type. ...
今度からは少なくとも自分でどこをどう探したかぐらい示そうな。 >>841
嘘つけ。キャストした場合についてはどこにも書いてない。
型が普遍なんてのは、君が勝手に思い込んでいるだけだ。
というか、いわゆる「強い型」ってのはそうらしいが、C++はそうじゃないだろ。
ちなみに俺も反論を用意してたところだ。
https://godbolt.org/g/viYhGj
中身は795の場所で、ついでだから f = *(double*)&i; を試した。
予想通りこちらはfmov(movsd)が出た。(最適化は切ってある)
つまり、俺が768で言ったように、
*(long long*)&f = i; // mov命令でコピー
または
f = *(double*)&i; // fmov命令でコピー
になるんだよ。少なくともgccはキャストされればその型だと認識している。
君はこれを矛盾無く説明出来ないだろ。 >キャストした場合についてはどこにも書いてない
はて、N4700の6.10/p8ほぼそのままの文面が少し上に貼り付けてあったような…
>>821
N4700 3.9, 4.5/p1, 6.8全般, 6.10/p8, 12.3/p1, 12.3/p(5.3), その他「launder」が登場する記述全般 正しいそうなコードが吐かれたことは未定義動作でないという証拠には全くならない
なぜなら未定義動作というのは
コンパイル時のエラー、実行時のエラー(または例外)、一見正常っぽく気体通り動く、その他、
というあらゆる事象を包含し得るので、、、
もちろんコンパイラの変更で(ことによったらコンパイル条件の変更だけでも)
ある日突然狂ったコードが吐かれる危険性があるが
そうなっても未定義動作をプログラムした人の責任
よって現時点で正しいげなコードが吐かれることをいかに力説しても無駄で、
規格の矛盾の指摘にはつながらない >>842
オブジェクトの型に関与しない操作についていちいち記述があるわけないだろ。
まさか「〜によりオブジェクトの方は変わらない」とかの記述が全演算子&標準関数その他諸々について必要だ
なんて言うわけじゃないよね?
未定義動作の結果はなんでもアリだと言っただろう。
その結果(想定の命令コードが生成されたこと)が未定義動作の結果のひとつだとして、何の矛盾も無い。 inline const self_type *const_this()
{
return this;
}
template <typename T_TYPE>
inline T_TYPE *drop_const(const T_TYPE *obj)
{
return const_cast<T_TYPE *>(obj);
} そう言って居直るやつは問題だが
ソースを読まない言い訳にするやつもダメ
腐敗は両岸から起きうることだ >>844-845
うむ。それは一理ある。
>>845
では逆から行こう。reiniterpret_castのど頭、
> 5.2.10 Reinterpret cast
> 1. The result of the expression reinterpret_cast<T>(v) is the result of converting the expression v to type T.
vをTに型変換したのが結果だとそのまま書いてある。
これはどう解釈すれば、「型はどうやっても変更できない」と取れるのだ?
さすがに無理だろ。
> 7. An object pointer can be explicitly converted to an object pointer of a different type.
これも型を変更できると読めるが。そして再び1に戻ると、
> 1. ---- If T is an lvalue reference type or an rvalue reference to function type, the result is an lvalue;
つまり当然有効なlvalueであり、デリファレンスも可能だ。
だからキャストを反映してmovなりfmovが出るのだ。
違うか?
君が言うようにメモリ上の型が普遍なら、どうやっても i には fmov が出ては駄目だろ。
(と思ったが、君は837ではないのか、、、) >>849
If T is an lvalue reference typeという但し書きがついているよな
(double&)ならlvalueだが(double)は違う >>849
> これはどう解釈すれば、「型はどうやっても変更できない」と取れるのだ?
式の型 (static type) は変わるが、オブジェクトの型 (dynamic type) は変わらない。
> 君が言うようにメモリ上の型が普遍なら、どうやっても i には fmov が出ては駄目だろ。
未定義動作ならなんでもアリだと言った。 >>851
それで突っぱねるのなら平行線だね。
俺は仕様書に詳しいわけでは無いから動作から説明するしかない。
君は仕様書には詳しいようだが、キャストした場合にも型が変更されないという記述を出して来れない。
ま、デッドロックだ。
とはいえ状況は色々分かったよ。ありがとう。 >つまり当然有効なlvalueであり、デリファレンスも可能だ。
仕様を引用して説明されてもこのとんちんかんな発言を繰り返すあたり、
知らないから間違えているのではなくオツムが悪いので必然的に無知になったと言うことに>>851は気付くべき >>852
> 俺は仕様書に詳しいわけでは無いから動作から説明するしかない。
なら↓お前の理解に基づいてこの動作を説明できるか試してみるといいかもしれない。
https://wandbox.org/permlink/2aKzO4VN3KRDB6Gu
> 君は仕様書には詳しいようだが、キャストした場合にも型が変更されないという記述を出して来れない。
式の型 (static type) とオブジェクトの型 (dynamic type) は別物だという客観的な
前提 [intro.defs] を素直に読みさえすれば何度も見えてるはずなんだけどな。 こいつわかってて引っ掻き回してるだけのような気がするわ
そうじゃなかったら馬鹿すぎる ある型の変数を入力として、別の型にキャストされた値を返すのはそりゃできるだろう
元の変数の型を変えることはそりゃ無理だろう >>854
それは何も不思議じゃ無いと思うが。
例の最適化もされてるし。
どこが俺の理解と矛盾してるつもりなんだ? >>857
お前の中でどういう理解になっているかは把握できていない。
その答えからすると、
"*(long long*)&f = i;" なら未定義動作にならないけど "auto p = (long long*)&f; *p = i;" なら未定義動作になる、
という理解なのかな。まぁそんなことは無いんだけどさ。 いやまあ無いんだけどな。
いつまで言い張る気なんだろうか。 あると言えばあるんだけどな。
そろそろごめんなさいしてはどうか。 strict aliasing ruleについてはここで解りやすく解説されてる。自分で怪しいと思う奴は読め。
http://d.hatena.ne.jp/yohhoy/touch/20120220/p1 >>858
ああそうだぞ。それは>>815で既に言ったし、実際に発現事例は今のところ全てaliasされてる。
顕在化させるには、「別型」で「alias」しないといけないんだよ。
オプションの名前も全くそうだろ。
多分君は理屈が分かってないんだ。
あれはtypeグループごとにメモリフェンスしていて、
別typeグループに入っていると結果的にout-of-orderになるだけなんだよ。
それは常時動いている。
ただし different type で alias して無いと顕現しない(ユーザ側には見えない)というだけ。
だからその可能性がある部分にwarningが出る。
しかしwarningというのは「普通やらないけど大丈夫か?」であって「絶対駄目」ではない。
結局君は different type alias について正確に理解出来てないんだよ。
上記を覆したければ、alias無しで different type alias の最適化がかかっている例を持って来い。
君の言う、
> まぁそんなことは無いんだけどさ。
の例だね。多分無いから。
既に言ったがLLVMだからインデックスレジスタは完全に残るんだよ。(多分)
キャストを知らないのだから理解出来ないようだが、(long long*) 部分は命令にならない。
(これはC++仕様書にも明記してあるが、C界では常識)
だから *&f だけが残り、結果、
*(long long*)&f と *&f (=f) は同じLLVM命令になる。(はず)
だからそこは問題視されてないんだよ。最適化器からも同じに見えるから。
逆に考えてみろ。同じtypeグループ内、例えば int と int が out-of-order になったら話にならんだろ。
だから同typeグループ内は alias があっても in-orderになってる。
そして別グループ double と int は常にout-of-orderになってるが、当然、関数でつながれているときにはフェンスされる。
例えば int a = max_idx(double*) みたいな感じで、doubleの配列から最大値の添字を取るときとかね。
だから different type で alias して無いとそれが見えないようになってるんだよ。
というのが俺の理解だ。覆す例があればよろしく。 いきなりレベルの低い話で割り込んで恐縮です。
よろしくお願いいたします。
久々にJava から C++ に移行して、簡単なイテレータパターンを実装しました。
Java で書いた
https://ideone.com/DJ9pI5
を元に C++ で書いてみたのがこれです。
https://ideone.com/FwNlc4
ここで、コンテナにあたる Aggregateクラス(具象クラスは BookShelf) の中に
イテレータ(Iterator:具象クラスは BookShelfIterator) を作成して返すメンバ関数 iterator() を定義していますが、
C++ だからデストラクタも定義しないとね、と考えて
当初、Aggregate クラスに仮想メンバ関数 delete_iterator() を書いて
Aggregate::iterator() と Aggregate::delete_iterator() を対にするように作っておりました。
しかし教科書をみると
Aggregate::delete_iterator() みたいなデストラクタはそもそも定義しないようで、
普通に
Iterator *it = BookShelf(具象クラス)->iterator();
delete it;
でなんの問題もないようです。
なぜ、これで問題がないのかトンと見当がつきません。
イテレータを作った具象クラスの中でデストラクタを定義する、というのならば分かりやすいのですが、
抽象クラスのポインタをキャストもせずに直接 delete できるのは、どういうからくりになっているのでしょうか?
よろしくお願いいたします。 >>863
> 上記を覆したければ、alias無しで different type alias の最適化がかかっている例を持って来い。
これでいいかな。
https://wandbox.org/permlink/RNDO0CIl9UpsaRwQ >>869
せこいわw
gcc7.2.0(そこの最新版)で%eにしたら見えるがな。
まあ努力はご苦労様。
とはいえ、gcc4.4.7ならこのコードでも顕在化するし、「aliasが要る」という要件が怪しいのは認める。
この最適化はまだ発展途上のようだね。 >>870
おっとすまん、輻輳してしまったが、869で問題なく分かったぞ。
そして両方とも、gcc7.2.0にするか、globalにすると直る。
したがって、 different type alias で問題が発生するのには 「aliasが要る」という俺の見解は間違いだ。
ただ、過度の最適化による不具合を防ぐ努力は行われており、
gcc4..4.7→gcc7.2.0でこのコードに関しては修正されてる。
とはいえgcc7.2.0でもどこまで動くか分かった物ではないね。 >>868
それが virtual の効果だとしか。
基底で virtual 宣言したメンバ関数群はそのポインタをまとめたテーブルが作られ、オブジェクトはそのテーブルを指すポインタを持つ。
派生のオブジェクトは派生側の関数群を指すポインタテーブルへのポインタを持つ。
だから virtual を使うと「変数の型ではなくオブジェクトが呼出すべきメンバ関数を知っている」という状況を作れるんだよ。
ただ、基底のデストラクタを virtual に指定しないときでも見かけ上は型システムをパスしてしまいコンパイルエラーにならない場合がある。
これは未定義だからやっちゃダメだよ。 >>875-876
うーん、普通のポリモフィズムの話が同様に適用できるんですね…
Base<-Derived1
Base<-Derived2
の基底・派生関係のとき
Base *p = new Derived1() ならば、delete p; は delete (Derived1 *)p;
Base *p = new Derived2() ならば、delete p; は delete (Derived2 *)p;
となる、と考えていいでしょうか。
Base *p = new Derived1() ならば、p->method(); は p->method_Dirived1();
Base *p = new Derived2() ならば、p->method(); は p->method_Dirived2();
という話と同じなんですね。
んーなせ Aggregate::delete_iterator() を作らなくちゃ、と考えたのか逆にわからなくなってしまいました…
ありがとうございました。 次に >>868 のテンプレート版を書いてみました。
https://ideone.com/LO68r5
void * (Java の Object)をキャストするのを嫌ったという理由になります。
>>868
>class Iterator
>virtual void *next() = 0;
>class BookShelfIterator : public Iterator { };
>void *BookShelfIterator::next()
>Book *book = (Book *)it->next();
https://ideone.com/LO68r5
そこで不思議に思ったことなんですが、
コンストラクタは
template <typename T> class Derived : Base { public: Derived(){}; };
とテンプレート引数 T をコンストラクタ名をつけなくていい(public: Derived<T>(){}; としない)のに、
デストラクタは
template <typename T> class Derived : Base { public: ~Derived<T>(){}; }; (クラスのメンバ関数宣言)
template <typename T> Derived<T>::~Derived<T>() { } (クラスのメンバ関数定義)
とテンプレート引数 T をデストラクタ名につけないといけないのでしょうか?何か分かりやすい理由はありますでしょうか? >>877
キャストとは意味が違うんだよ。
上でさんざん議論してる static type と dynamic type の話とも関係あるのかなぁ?
入り組んでてよくわからん。
型はあくまでも Base* で、仮想関数テーブルを辿って必要な関数を呼び出すってだけだ。
繰返すけど、 Base のデストラクタに virtual がついてないときに Base のポインタに対して delete すると
Base のデストラクタが呼び出されるだけになってまうので気をつけてな。
派生クラスのデストラクタが空っぽのときでもデストラクタが呼び出される必要はあるらしいぞ。 >>878 の続きです。
同じく、テンプレート版
https://ideone.com/LO68r5
にて一点不満におもったことがあります。
>>878 では基底クラスの記述について、
template <typename T>
class Iterator {
public:
virtual T *next() = 0;
};
派生クラスは
template <typename T>
class XXXIterator : Iterato<T> {
public:
T *next();
};
template <typename T> T *XXXIterator::next() { ... }
と書きました。
しかし本当は、基底クラスを純粋に一個にしたいと希望しているのです。
つまり基底クラスにテンプレート引数Tを書きたくない。
class Iterator {
public:
virtual ○○○ *next() = 0;
};
と基底クラスを一つだけにしぼりつつ、
派生クラスにテンプレート引数を使用して記述することは可能でしょうか?○○○に書けるなにかいい記述はないでしょうか?
テンプレート引数を使用した具象クラスに対応する、テンプレート引数を使用しない抽象クラスを書くことは可能でしょうか? >>878
付けなくてもいいし、付けても通るってのは私は今初めて知った。 >>880
強引なキャストで出来る可能性はあるかもしれないけど、
常識的な方法では出来ないと思う。
ただ、そもそもそういう継承関係を作る必要は無いんじゃないか。 >>879
ありがとうございます。
meyers の effective C++ 第7章を読み返しています
C++ には Java の fainal がないので、うっかり、std::string や std::vector を派生させてしまうところでした、危ないなあ… >>868
混乱するならシンプルに設計したら?例えばこんな感じ?登録して表示するだけなら簡単でしょ?
#include <stdio.h>
#include <string>
#include <vector>
class Book{
public:
std::string name;
Book(std::string _name) : name(_name){}
void show(){printf("%s\n",name.c_str());}
};
class Books{
public:
std::vector<Book *>m_list;
Books(){}
~Books(){for (auto p : m_list) if (p) delete p;}
void addBook(Book *p){m_list.push_back(p);}
};
int main(){
Books books;
books.addBook(new Book("aa"));books.addBook(new Book("bb"));
books.addBook(new Book("cc"));books.addBook(new Book("dd"));
for (auto p : books.m_list) p->show();
// iterator使いたいなら
//for (auto it = books.m_list.begin(); it != books.m_list.end; it++) (*it)->show();
return 0;
} >>880
Java のことはあまり知らんので元ネタにした Java 版の方をよく見てなったけど、
interface のかわりに抽象クラスを使おうとしてたのか。
似たような機能に見えちゃうかもしれないけど、インターフェイスを強制する方法としては抽象クラスはあまり良くない。
C++ 的にはコンパイル時にディスパッチする多相と実行時の多相があって、
抽象クラスは実行時にディスパッチする仕組みなのでコンパイル時に確定するはずのことを実行時にするのはクソザコという風潮。
だけど「コンセプト」の機能が C++ に導入されるのが延び延びになってていまだ入ってないので、
traits とか SFINAE とかを使ったまわりくどいメタプログラミングで代用してるのが実情なんだ。 >>881
>付けなくてもいいし
うーん、デストラクタの場合はテンプレート引数をつけないとおこられちゃいます…
×https://ideone.com/x5FrwU 69行目
○https://ideone.com/FUJ3OO 69行目
よくわらからないな… >>886
いや、型名の方には付ける必要あるよ
×:
template <typename T> TShelf::~TShelf() { delete [] (this->t_s); }
〇:
template <typename T> TShelf<T>::~TShelf() { delete [] (this->t_s); }
△: 知らんかった
template <typename T> TShelf<T>::~TShelf<T>() { delete [] (this->t_s); } >>884
はい、すごくよくわかります!!
std::vector とか、std::list とかstd::deque とかは、たぶんいけると思います。
http://mevius.2ch.net/test/read.cgi/tech/1434079972/14
http://mevius.2ch.net/test/read.cgi/tech/1434079972/19
なんとなくデザパタ本を読み返していて、車輪の再発明に没頭してしまいましたが、C# のデザパタ本、というのも聞かないし、もうデザパタは古いのかな… >>887
ありがとうございます。確認いたしました。 >>885
夜遅くにコメントいただきありがとうございます。
>C++ 的にはコンパイル時にディスパッチする多相と実行時の多相があって、
理解できます。コンパイル時に確定できるのなら最大限それに努める思想はたとえば constexpr にも現れていると思いました。
>抽象クラスは実行時にディスパッチする仕組みなのでコンパイル時に確定するはずのことを実行時にするのはクソザコという風潮。
うーん、たぶん私が周回遅れなだけだと思いますが、じゃあ、ひところ、あれほどまでにもてはやされたデザインパターンは、どこにいってしまったのでしょう…もう誰もやらないのかな… >>887
なんでこうなってるかっていうのは割と感覚的にやっちゃってるからうまいこと説明できひんのやけど。
クラステンプレートの中に関数テンプレートも書けたりするので
template<class T>
class foo {
public:
template<class U> void bar(void);
};
実装書くときはどれがどれに掛かってるかわかるようにせんといかん
template<class T> template<class U>
void foo<T>::bar(void) {
}
みたいな話なんじゃないかとコンパイラの気持ちになる仁奈ちゃんの気持ちになってた。 >>892
抽象クラスを使うパターンなんてのがあるわけ? GoF 本とか読んだことないから知らんけど。
それはインターフェイスをまとめた何かを作れって話とかじゃないの?
C++ の抽象クラスを使えって話とは違ったりしそうだけど。
デザインパターンはあくまでデザインの話なんだから言語の具体的な機能はその時代に有るものでやるしかないし、
よりよい機能が提供されるようになったら使うだろ、そりゃ。
抽象クラスを使うやり方しかできないなら「デザイン」を学び取れてないってこった。
まあ今は C++ への理解も十分でないからってのもあるだろうけどさ。
ところで QZ って C++ スレの常連みたいに思ってたけど、
その割にアレなのでひょっとして共通トリップだったりするの? >>894
>その割にアレなのでひょっとして共通トリップだったりするの?
単に、あれよあれよと、また、次から次へと忘れていくので、ぜんぜん進歩しないだけなのでした。
こんな感じ… https://www.youtube.com/watch?v=Hflpt1-kAl4 手元に古いGoF日本語訳(1999年初版)があったので覗いてみたら、
Iteratorのサンプル(C++)が>>880みたいに抽象クラスで実装されていてびっくりした。
抽象クラスを使わなくても、処理の共通化を考えないなら問題ないし、
共通化したい場合でも、そこだけテンプレート化すればよいような気がする。
https://ideone.com/sFzBq4 VC++とか今でこそまともだけど昔はテンプレート周りがうんこすぎて風呂釜洗剤教の人のやり方に頼らざるを得なかったらしいね そういう「まとも」を求めてVCを選ぶのは情弱のすることだ
意味の違う「まとも」で定評のあるコンパイラであって Vistaまではgccでコンパイルしてたらしいからな。 usingは時代によって使える機能が異なる
昔はnamespaceから使える宣言を取り出す役割
最近は=を用いてtypedefの簡略化っぽい書き方が出来る 将来的にはusingがプロパティの役割まで担ってくれると余計な予約後増やさなくて済む希ガス >>897
最初なんてタダのマクロだったし、
4.xだってテンプレート使うと名称長さ制限にかかったり
STLのBUGは何時までたってもそのままだし ratioのバグとかinitializer_listとかね
しっかりしているようで時おり大ボケで笑いを取る謎な会社だ >>883
重箱の隅だけどC++にもfinal導入されたよ、C++11からだっけ
stlに付いてるかどうかは覚えてないけどw 重箱の隅じゃあんめえ
仮想デストラクタがないことと継承禁止は近いが違う std::vector とかを public 継承してもスライシングが起こらないように使う分には全然問題ないわけだしな。
でも人間はアホだからスライシングするし、スライシングしたときにコンパイルエラーにしてくれないから避けようっていう「習慣」なだけで、
言語機能としてはデストラクタが仮想になってないからといって継承が禁止されているってわけではないんだ。
そこらへんは確かに意味づけが違う。 デザパタは基本的にGC言語向きだしな
C++とは相性が良くない C++の基本的なコーディングを学ぶのにオススメな書籍あるかな?
テクニック集とかもあると読んでみたいと思っている EffectiveC++シリーズ
Exceptional C++
C++ Coding Standards
あたりの定番中の定番でいいだろ ここって本職でやってる人らばっかりなんかね
日曜プログラマが気安く書き込んでもいいのだろうか >>911
いいよ。 俺も趣味プログラマだけど偉そうに書き込んでるし。 GoF本のうち
Stateパターンは抽象クラス必須
Abstractなんちゃら系も抽象クラス必須
な印象 >>911
プロがここでうんちく垂れてたら引くわな >>873
最新版で該当ケースを探せず、
わざわざ5年前の版を持ち出してきてまで俺ツエーしたいヘタレを相手にしてしまい、すいませんでしたー
gcc4.4.7(2012/3/13)の時点で対応できて無いという情報はものすごく役に立ちますー(棒)
つかマジで、賢いつもりなら最新版で該当ケース探してgccに報告しろよ。
問題に遭遇したらとりあえず最新版、というのは基本だ。
ここを問題視する奴がgcc4.4.7なんて今使ってるわけないだろ。お前は馬鹿なのか?
お前のその努力は誰の為にも役に立ってないだろ。
これは多分に政治的問題で、コンパイラ屋がごねているだけだ。
既に言ったとおり、
reinterpret_cast相当のことがなされている場合、その関数単位で -fno-strict-aliasing すればいいだけで、
これに関して技術/仕様的問題は何もない。
ただ、「ソースさえ正しければこんな問題は発生しない」とか言って、コンパイラ屋がごねてるんだよ。
だから、力関係が逆転すればいきなり全部直ってもおかしくない。
gcc7.2.0がどっちのアプローチ、
つまり、上記の通りばっさり最適化を切ってしまい、最適化ケースを積み上げる方向にしたのか、
或いは従来どおり、過度の最適化を検出し、最適化を防ぐケースを積み上げることにしたのかは、俺は知らない。
ただ、どちらのケースであっても、最新版で上手く行かないケースがあれば、それはgccにとっては有用な情報なんだよ。
それをわざわざ旧版で、しかも隠してしれっととか、意味無いしせこいわw
最新版で出現しないから焦ったか?小物感ありあり。
> まぁそんなことは無いんだけどさ。
とか言うから、お?釣りか?ならここは全力で釣られてやるさ、該当事例持って来いよ!って流れなのに、
事前に該当事例用意しておかずに釣りとかアホかテメーは。
君が最新版で完全にアウトなケースを用意してれば、ああこれは完全に俺の負けですサーセン、とお後がよろしかったのに、
gcc4.4.7であることにも触れず俺ツエーするとか、小物過ぎて泣ける。
お前もうちょっとスレの流れを考えろよ。 >>908
GoF本はc++とsmalltalkだったろ テンキー風のボタンの並びでモードによって意味が変わる(Num Lock ON/OFFのもっと複雑化したようなやつ
というユザーインターフェースの実装はStateパターンのどくだんば
そこまでレトロなのでなくてもGUIでお絵かきツールを集めたツールボックスなUIとか作ると
Abstructなんちゃらパターンのどれかを再発明しているケースが多いと思う >>913
昨日 >>885 でまわりくどいメタプログラミングと言ってたのがそれだ。
State パターンのように特定のメンバ関数を持っていることを強制したいときには
それを判定するトレイツを作って対応する。
たとえば >>886 にあるコードを対象に考えて、
「あるクラスがそのクラス自身のポインタを返す next という名前のメンバ関数を持っているか」
を判定するトレイツはこうなる。
template<class T>
class has_next {
template<class U, class V = T>
struct helper : std::false_type {};
template<class U>
struct helper<U, typename std::enable_if<std::is_same<decltype(std::declval<U>().next()), U*>::value, T>::type> : std::true_type {};
public:
static const bool value = helper<T>::value;
};
C++ 標準の type_traits を真似してるので使い方もだいたい同じ。
static_assert(!has_next<TShelfIterator<Book>>::value, "TShelfIterator must has next() method.");
みたいに書いておけば TShelfIterator<Book> がメンバ関数 next を持っていることが保証される。
持っていなければコンパイル時にエラーになるから。
ここではひとつのメンバ関数を判定するだけのものを作ったけど、 Boost にはもっと汎用的にいい感じにかけるやつが有った気がする。
知らんけど。 あるファイルに下のような文字が書き込まれていて
xxxx=3
これの3を取得する完璧無欠なロジックなにかないかな >>923
俺様のアルゴリズムは完璧だぜ!!!
ってだけ
まあそんなのないんだけど書き込みたかった リバースイテレータをfindしてイコールでセパレート。
って、数行から見つけるのか。
構文解析とかか? >>926
数行から見つける
設定値の中から見つける
実際は
#xxxはdddの設定値
xxx=1
#yyyはcccの設定値
yyy=3
こんなのが繰り返し書かれてる
正規表現確かに良さそう忘れてた float演算がdoubleよりも遅いってアジですか? >>932
すんごく綺麗なコードありがとう
見事に魔改造して糞コードにしてしまう自信がある >>927
そういう設定ファイル的なものを読むならkeyとvalueのペアのリストつまりmapを返す実装を考えた方がいい >>934
俺もそうは思ってるのだけどその読み込む処理をどうしたら綺麗にできるかなぁって悩みなんだ
マップ作ったあとに検索が綺麗なのかなとは思ってる 文法的には LL(1) かな?
素朴なパーサコンビネータでも充分に足りるのでその手のライブラリを導入すると楽にパーサを作れると思う。
それはともかく、「>>922 みたいな」というだけの仕様では
・数値以外が設定値にくることもあるのか?
・要素に改行を含められるのか?
・エスケープも出来るようにするのか?
等々が読み取れないし、多分 >>922 は考えてないんじゃないかなと思う。
オレオレ設定ファイルフォーマットを考えるくらいなら TOML とかいったよくあるフォーマットを採用すれば
ライブラリが充実してたりして便利なので考えてみるといいかも。 ってかboostのPropertyTreeにiniパーサーがあるからそれ使うといいよ >>936
回答すると
数値以外もありうる
改行は値として入れない
エスケープってなんだろう?
xxxに関しては最大16文字の文字列(大文字小文字計52文字の組み合わせ)
たったこれだけでも深いね
ソフトウェアって神秘 ini-parserてのがなかなか良さそう
picojson,rapidxmlなどが好きな人にはいいかも 構文解析したいならbisonでも使ったらいいんじゃね? >>938
>>922の完璧無欠なロジックてのは
最初に完璧無欠な入力規則を作ってから議論できるものだろ
>数値以外もありうる
数値だけでもいろんな型があるわけだしこの程度じゃ何も語れない
xxxx=3のような単純な形式はINIファイルとか>>936のようなのとか利用するのが便利
最近はXML形式が推奨されてる
ただしどれもが完璧無欠とは言えないけど XMLは配列が直接表現できないし手で書くのがクソめんどくさいし見づらい
その点JSONの方がずっとマシなんだけど標準JSONだとコメント書けない 人が書く設定ファイルならtomlがパースのしやすさと書きやすさでバランスが良いと思う >>946
dein.vimで使われてるの見て知ったけどまったくと言っていいほど広まらないね
>>944
ド定番のYAMLでいいじゃん Cargo の設定ファイルも TOML やぞ。 モダーンな言語のモダーンなツールは TOML がトレンド。 これ。
YAML みたいにインデントで構造を表現するのってパースめんどくさい。
個人的に YAML は不格好に見えて好きじゃないっていう主観もあるんだけど、
YAML ってそんなに定番ってほど目にしたことが無いな〜と思って考えたら
たぶん俺の巣は Scheme スレやからやな。
Lisp 界隈では設定ファイルにはS式を使ってまうもんな。 luaなんかもよく使われるけど、schemeやluaが設定ファイルとして使われるのは
呼び出し側の言語が同じであるか、他の用途で使うためにすでに組み込んでる場合がほどんどで
設定ファイルだけの為にLL組み込むにはお手軽とは言えないかな
TOMLはいいとは思うんだけど
自分が使うなら仕様が固まってからの1.0〜は必須で
↓で300程度は使われてからかな
$ apt-file search toml | grep "\.toml$" | wc -l
0
$ apt-file search json | grep "\.json$" | wc -l
3611
$ apt-file search yaml | grep "\.yaml$" | wc -l
1480 最近この手の話題に疎いからtomlとか知らんかったのでちょっとググったけどまあ好きなの使えや
って感想しかないわ
https://gist.github.com/miyakogi/e8631ce5f7c956db2313 パースの楽さだけで言えば JSON が優勝だけど人が手書きするには色々アレだからな。 ES5以降ケツコンマOKになったんだからJSONも新規格にすりゃいいのに。 >>936
正規表現で済んでいるのになんでスタックが要るんじゃ!!!!!!11!1!!!! 文脈自由文法は解析にスタック(理論上は無限の段数のやつ)が要るクラスだが
正規言語は有限状態マシンで済む言語のクラス
今話題の設定言語は無限の入れ子は持たなそうなので正規言語で逝ける、 ん〜、そのへんの学問的な分類はよう知らんけど、取りうる状態は有限でもバックトラックは起こるしそのためのスタックは要るんちゃう?
同じ文法の構文解析器を作ればどっちのアプローチでもスタックの消費量はかわらんと思うんだけど。
より制限の強い方で「十分」っつーならそれはわかる。 C++ 標準に入ってる機能で出来りゃ楽だしな。
ただ、正規表現ライブラリだとエラーの検出場所の伝達方法とかで融通が利かなかったりするので、
ユーザーが入力する設定ファイルを解析するパーサを作るとなると作りこみ難いという感触があるかな。 >>958
>ん〜、そのへんの学問的な分類はよう知らんけど、取りうる状態は有限でもバックトラックは起こるしそのためのスタックは要るんちゃう?
非決定性有限オートマトンは決定性有限オートマトンに変換できるので、
バックトラックが一切起こらない形に書き換えることは可能。
lexなんかだと、そのような変換を行ったコードを生成していたはず。
ただし、プログラム言語などで一般的に使われる正規表現は、
ここでいう正規言語を拡張したものなので、この限りではない。 またまた低レベルな質問で恐縮しております。よろしくお願いいたします。
https://ideone.com/MXvhkC
ここまで実装できている状態で、演算子 += を定義するには、どのように書けばいいでしょうか?
なお実際に作業している対象は自作の多桁長演算ライブラリで、operator+=() を operator=() や operator+() を再利用できればうれしいな、と考えております。
operator+() や operator=() に書いていることを、繰り返して書くのは避けたいと考えているのです。 普通はoperator+=()を実装してから、それを使ってoperator+を実装する >>965
なるほど
https://ideone.com/t89oo1
しかし、+=, -= ならまだしも、 *=, /=, %= を考えると、なんだか似たようなコードを二箇所に書きそうな雰囲気がします… >>967
これってなんでprivate継承なのか分からない >>970
スライシングを起こさないようにじゃないの。
デストラクタを virtual にすると要らん仮想関数テーブルが作られちゃうからな。
それでいて定義する関数は friend 関数にしてるから外側からでも見えるんだな。 >>969
こんな小題でもいろいろと試されるんですね…
たしかに operator+=() は、意味からいっても friend である必要はまったくないですね。
一方 operator==(), operator+() は式の表現としての対象性を保存したいので、friend をつけたいと考えています。
operator<<() に対しては friend を必ずつけないといけないようですが、その理由はよくわかっていません。
https://ideone.com/pR0EP1 IDE使っていて思うのがtemplate関数でデフォルト引数classAを設定すれば、
template<typename T=classA>
void Test(T tmp){
tmp.func(1, 2, 3);
}
上記のtmp.のところでclassAの関数とかが出て来るようになると嬉しいとか思ったり
コンセプトとかで対応できるようになるんでしょうか? mix-inもまともに知らないやつがなぜ回答してるのか… >>973
言語仕様っていうよりIDEの性能のような。
コンセプトまで構文解析してサジェストするようになれば確かにできるかもしれんけど。 >>973
技術的には可能だからlibclangでなんとかなるようになるなら誰かやってくれるかもね
コード補完にプラグインを使えないIDEなら開発元にリクエストするしかない mix-inで理解が止まっている人がなんか吼えてますな >>973
コンセプトはシンタックスの誤りを判定するのみで型情報を持っていないため
その補完は期待できない >>977
boost operatorsのprivate継承がmix-in以外のなんだと思ってるんだ? C++を勉強しようとしてるんだが
基本的にCの書き方が一般なのか
C++の書き方が一般なのか教えてもらいたい コーディングスタイル?
そんなの好きにすればいいよ >>982
Cの書き方とかC++の書き方とか一般的とかない
「一般的」なるものを求めたいならメジャーなIDEのデフォルトのオートフォーマットだろうな >>985
operator+= の返却値は参照にしといた方が辻褄が合うので良いよ 関数内で作ったベクターやマップは関数を抜けたらメモリ解放されると考えてよかです? >>988
記憶クラスによるとは
スマホで打ってるから書式とかガタガタだけど下みたいなことしてる
createmapってのを抜けたときにvectorもmapも解放されると信じている
vector XX( *map)
{
要素数二個のstring型のvectorデータを作成
return vector<string> ←要素数2
}
createmap ()
{
map<string,string> y
{
vector<string> tmp = XX(&y)
y.insert( tmp[1] , tmp[2])
}
} うん、信じていい
XXから抜けるときにムーブコンストラクタでtmpへ移動され
createmapから抜けるときに解放される
このときoperator deleteが呼び出されるが
operator deleteがどのようなタイミングで解放しているかには依存すべきでない
我々が関心を持つべきはoperator deleteが呼び出されるタイミングで実装の詳細ではない >>989
static 付きで宣言してればプログラムの終わりに解体されるし、
new で作れば delete されたときが解体されるし、
そうでなければスコープの終わりに解体される。
「関数内で作った」というだけでは情報不足。
>>989 のような例であればスコープの終わりで解体されることは保証される。
それと >>990 はムーブコンストラクタの話を出してるけど C++17 以降ではこういう場合は RVO の発動が必須になってなかったっけ? >>991
990だが、何を言っているのか、悪いがよくわからん
XXがcreatemapとは別の翻訳単位から外部結合されている場合でも
その何だ、ムーブコンストラクタの回避(?)が必須になったのか? >>992
そう。 RVO 必須だからコピーコンストラクタもムーブコンストラクタも無いクラスでも OK っていう新しいルール。
https://wandbox.org/permlink/X6g7JSpkSl82VvtZ >>994
いや >>993 みたいなのは C++14 以前では NG になるよ。 このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 45日 16時間 56分 20秒 5ちゃんねるの運営はプレミアム会員の皆さまに支えられています。
運営にご協力お願いいたします。
───────────────────
《プレミアム会員の主な特典》
★ 5ちゃんねる専用ブラウザからの広告除去
★ 5ちゃんねるの過去ログを取得
★ 書き込み規制の緩和
───────────────────
会員登録には個人情報は一切必要ありません。
月300円から匿名でご購入いただけます。
▼ プレミアム会員登録はこちら ▼
https://premium.5ch.net/
▼ 浪人ログインはこちら ▼
https://login.5ch.net/login.php レス数が1000を超えています。これ以上書き込みはできません。