C++相談室 part147

■ このスレッドは過去ログ倉庫に格納されています
2019/12/18(水) 17:56:53.03ID:uFDqtnkl
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。

前スレ
C++相談室 part146
https://mevius.5ch.net/test/read.cgi/tech/1573094136/
このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.105【環境依存OK】
http://mevius.5ch.net/test/read.cgi/tech/1556142878/

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

[C++ FAQ]
https://isocpp.org/wiki/faq/
http://www.bohyoh.com/CandCPP/FAQ/ (日本語)

STLつかうと一気に実行ファイルサイズが10倍に?!

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

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

↑え?だってお前、普通ダイナミックリンクするだろ?
"ダイナミックリンク"す・れ・ば、ファイルサイズ**増えないです**
2020/01/19(日) 19:46:34.82ID:fzpRtoDi
>>380
そのくらいしか思いつかなかったが、>>297はその程度の主張だったんじゃないの?
じゃあどういう主張しているとID:PgEzQeWdは解釈していたのかな。そっちが気になる。
2020/01/19(日) 19:46:39.94ID:6oeBvQPN
> かなり綿密に絡んだ話だろ

誤魔化しすぎというブーメランが脳天に突き刺さってるぞw
2020/01/19(日) 19:54:00.26ID:yQO+Nq01
なるほど。。こりゃ話しても無駄だな。
2020/01/19(日) 20:25:44.83ID:M/ehGL7C
gotoと例外安全性がどう絡むのかわからんボスケテ;
2020/01/19(日) 21:06:11.93ID:fzpRtoDi
話しても無駄以前に、結局gotoと例外安全がどう関係するのか一言も出てこなかったな。
2020/01/19(日) 21:10:50.68ID:CSTVsvTH
RAIIとgotoは混ぜられないだろ
2020/01/19(日) 21:13:01.22ID:AinWVopR
そらgotoでリソース開放ルーチンに飛ぶようなCスタイルのプログラム書くと
例外飛んできたときに死ぬって話でしょ
(いくらC++にfinallyが無いからってgotoでリソース開放ルーチンに飛ぶのはダメ)
ただし元々の質問には関係ない話なんだがな

ところでC++にfinallyが無いのはちょっと良くないよね
今となってはラムダで自作できるようになったからいいけど
2020/01/19(日) 21:16:51.88ID:fzpRtoDi
>>398
その「混ぜる」って具体的にはどういうことを言ってるんだろう。
2020/01/19(日) 21:24:53.93ID:AinWVopR
基本的に break や return も生き先の決まった goto なので
余ほど変な使い方をしない限りRAIIと goto を混ぜれないって事はないよなぁ
むしろ RAII を使わないで goto でC系のリソース開放をしていた場合にハマるって話では

まぁでもこれは
do{
  if( error ) break;
}while(0);
//開放処理
return;
でも同じことだし、元の質問には関係ないんだが
2020/01/19(日) 21:34:33.08ID:RfLx+x9F
まだやってんのか

>>377
それ
2020/01/19(日) 21:40:42.19ID:RfLx+x9F
do {
if(...) break;
} while (0);

よりは

{
if (...) goto label;
}
label:

の方が良い

という意見に賛成

>>303ではないけど
2020/01/19(日) 21:44:50.08ID:RfLx+x9F
まあどっちでも大差ないけど
2020/01/19(日) 21:47:25.68ID:RfLx+x9F
{
{
if (...) goto label;
}
}
label:

これはbreakじゃ無理
2020/01/19(日) 21:57:15.09ID:RfLx+x9F
{
switch (...)
{
case ...: goto label;
}
}
label:

これも無理
2020/01/19(日) 22:11:05.36ID:ByUy1Erg
while(0)とか意味不明なコードよりgotoでスコープ抜ける方がはるかにシンプルだわな
2020/01/19(日) 22:15:20.58ID:RfLx+x9F
一応 do while(0) の使い方も覚えておいた方が良い
他人のコードを見たりマクロで使ったり
する事もあるだろうから
2020/01/19(日) 22:17:28.52ID:JMAoH3/H
普段のdo whileもwhile(0)って書くなど弊害が出るのでやめた方がいい
2020/01/19(日) 22:19:27.67ID:ByUy1Erg
ループするつもりもないのにループの構文使うのは悪手だと思う
2020/01/19(日) 22:27:26.89ID:RfLx+x9F
>>409
日本語で
2020/01/19(日) 22:33:02.85ID:fzpRtoDi
そこはまぁ、ループではあるけれども同時にbreakが使えるブロックでもあるわけで、
実際do-whileなんてほとんどがそういう使い方しかされていないわけだし。
ループできる構文でループしないのはbreakできる構文でbreakを使わないのと
同じようなものかと。
2020/01/19(日) 22:36:02.43ID:JMAoH3/H
>>411
do whileしてるのになぜか1回しか実行してないのに気付くのに時間がかかる
習慣で書くのでwhile(0)に気づけない
2020/01/19(日) 22:48:25.05ID:PgEzQeWd
こんなささいな違いは個人の好みでいいと思う派
do-while使わない派の言い分もわからなくもないが、
ソースを読む場合gotoだってgoto先を確認しないと意図が理解できないだろ
label名を考える必要があるのもちょっとめんどい
なのでこんなのどっちでもいい
ちなみにrust方式もブロックの先頭にラベル付いてるのは若干違和感覚える
2020/01/19(日) 22:50:45.02ID:RfLx+x9F
>>413
誰か解説よろしく!
2020/01/19(日) 23:07:09.81ID:Wel1D6/w
どっちのやり方でも構わないけど、リソース◯◯を自動解放するためのブロックだとか意図を示すコメントを付けておいてくれればそれでいい。
2020/01/19(日) 23:13:56.14ID:AinWVopR
↑だからその方法だと例外安全が・・・
C++だとリソース開放は RAII か finally かしか幸せになれない
2020/01/19(日) 23:17:22.36ID:RfLx+x9F
その方法
ってどの方法?
2020/01/19(日) 23:23:50.28ID:Wel1D6/w
>>417
誤解させたかもしれないから補足すると、どっちのやり方もと言ったのはただのブロックかdo whileかという話のことで、どちらにせよスコープを抜けて破棄されることを想定していた。
解放ルーチンにとばすことは端から考えてなかったよ。
2020/01/19(日) 23:47:54.15ID:L2mlhsAt
解放ルーチンにとばすくらいしかgotoの有用な使い方なんてねーだろ。
だからRAII、例外安全の話になってるわけだが
もう意地になって意味もわからずgotoにこだわってる馬鹿がいる。
2020/01/20(月) 00:05:06.10ID:ThUag/92
finally相当のデストラクタをラムダ式で渡すクラスのインスタンスを作ればいいじゃない、
で済まされてしまいそうだがやはりfinallyはあったほうがいい。
2020/01/20(月) 01:01:38.84ID:KvAer05C
「解放ルーチンにとばすくらいしかgotoの有用な使い方なんてねーだろ。」
って思えるぐらい、Cではこの技法が多用された
なぜなら真実は逆で
「gotoでとばすぐらいしか開放ルーチンをまとめる方法なんてねーだろ」
だったから多用された
A→Bでなくて、実はB→Aだったって話

なんだけど、あまりにもB→Aが多用されたから
数の暴力で逆のA→Bも成り立つと感覚的に思ってしまう
だが本当にそうだろうか、gotoに開放ルーチンに飛ばす以外の利用法は無いのだろうか
模索してみよう、というのがスレの流れ

スレがその流れになるのは自明で
何故ならC++においては「gotoで開放ルーチン」は例外安全の意味で完全な悪手になったから
初めから勘定に入らないし、考える意味もないし、議論の余地もない
他の利用方法を前提に話すのは当たり前で既定路線
2020/01/20(月) 01:58:07.70ID:wNCym70P
スレの流れはvectorの動的な解放手段についてです
424デフォルトの名無しさん
垢版 |
2020/01/20(月) 05:25:12.27ID:KSbNzMqr
Javaはgotoを無くした先進設計だからな。
2020/01/20(月) 07:11:09.70ID:SZK6NMcF
>>410
ほんこれ
メインフレーム時代から「なぜ0を足すんだろう」なんてあったけど
そういう謎コード書いて俺スゲーってやる厨二病は痛いよな
2020/01/20(月) 07:59:32.82ID:hWOi4sNW
つまりgotoと例外安全がどうとか言っていた人はこんなC時代の技法を念頭に置いていたわけか。

if (fail) goto FINAL;

FINAL:
後始末

gotoとRAIIの相性が悪い、混ぜられないという話はまた別なのだろうか。
2020/01/20(月) 08:30:41.35ID:ItoFGwWk
>>426が例外安全かどうかとgotoは関係ないんじゃない?

>>273>>426のコードも関係ない

ただ例外安全て言いたかっただけと思う
2020/01/20(月) 09:55:56.39ID:SZK6NMcF
>>273
vector<usigned char> huge;
//do something
huge.clear();

gotoは全く関係ない
2020/01/20(月) 10:09:57.52ID:rZl1icD3
>>428
vector自体が確保したメモリが解放される保証がないのでNG
とっくに答えは書かれているのだから今からどやるのやめろ
2020/01/20(月) 10:14:06.16ID:SZK6NMcF
保証しないってどこに書いてあったっけ?
2020/01/20(月) 10:15:25.68ID:JGG/x92o
>>275
これで解決済みだよなぁ
std::vector<...>{}.swap(v)
2020/01/20(月) 10:15:47.05ID:N9WxJN6X
>>428
>>291,292辺りを見てこい
2020/01/20(月) 10:17:29.98ID:N9WxJN6X
もちろんclear()の仕様も確認しとけ
2020/01/20(月) 10:18:17.03ID:ThUag/92
>>292 で実装依存の最適化について言及がある。
あるサイズを超えるまではヒープではなくスタックを使うことで高速実行を期待する実装はあり得ると思う。
vectorの具体例は知らないが、EASTL::basic_stringはそうやってる。
2020/01/20(月) 10:40:56.82ID:SZK6NMcF
>>433
だから、どこに書いてあったのかと聞いているんだが
2020/01/20(月) 11:04:21.50ID:wNCym70P
>>431の言う空の一時オブジェクトとswapという常套手段で解決するのに質問者のクズは場当たり的などと難癖をつけ、
さらにじゃあnew/deleteしろよというまっとうな意見にバカを言うななどとほざいた結果がこのくだらねえ流れだよ
2020/01/20(月) 11:09:12.37ID:rZl1icD3
>>435
c++の規格書は有料だけど持ってんの?
ぐぐればstack overflowとかいくらでもひっかかるけど調べた?
これは割りと知られた仕様だと思うけどね
実際g++とかでやってみればわかるけどclearしてもcapacity変わんないから
2020/01/20(月) 11:14:14.45ID:wNCym70P
少なくともVC2019はclearでデストラクタが呼ばれてる
2020/01/20(月) 11:20:47.48ID:N9WxJN6X
>>438
それはvectorに格納した要素ごとのデストラクタの話であって、それらを格納するためにvector自身が確保した領域が解放されるわけではないだろ
2020/01/20(月) 11:29:18.51ID:SZK6NMcF
>>437
情報持ってるのに出してくれないのはわかったよ、無理にとは言わん
g++の挙動については情報ありがとう
2020/01/20(月) 11:53:45.15ID:JGG/x92o
むしろclearで解放せず、capacityが減らないことを保証してほしいよね
capacity減らす手段は用意されているのだから
2020/01/20(月) 12:32:03.74ID:xWGHAxxP
結局何を保証して欲しがってるのかさっぱりわからんが
言語仕様はvectorの何やらはもちろん、deleteだってfreeだって、OSにメモリ領域を確実にお返しになる事なんか保証してない事は覚えておこうな
2020/01/20(月) 12:33:54.17ID:RAANiraF
>>441
> capacity減らす手段は用意されているのだから
いや>>432はそれが確実じゃないって話だろ
まあそんな実装は見たことないけど
2020/01/20(月) 12:52:13.55ID:JGG/x92o
>>443
いや空とswapすれば減るじゃん
2020/01/20(月) 13:22:01.92ID:hv8WW6TF
>>444
空とswapは場当たり的に見えて却下と質問者様がおっしゃったからこの論争になったんだぞ
2020/01/20(月) 13:22:46.08ID:SZK6NMcF
>>442
OSに返すかどうかの問題じゃねえだろ
allocatorが管理するサブプールに還元でもいいわけで
447デフォルトの名無しさん
垢版 |
2020/01/20(月) 14:27:22.95ID:0GX6odYx
概出鴨試練蛾
do{...}while(0); と
{...} の違いって決定的なのは何かって
break; を入れられるかどうかだと思うんだけど
ループじゃないものに do{...}while(0); を使うのは可笑しいって派の人らは
後者に break; 入れられるようにしておけば良かっただけなんだよな
2020/01/20(月) 14:50:16.98ID:hv8WW6TF
ループする気もないのにループ構文を使うのは誤解の元
同様のことは他にもいくつも手段はあるのにループを使う必要がない
モダンな書き方だと[&](){...}();
2020/01/20(月) 15:02:12.80ID:KVDidwnp
違うだろ
while使わないよ派はgotoで充分だろ
ブロックを抜けるbreakが欲しいのは現状while使うよ派だろ
450デフォルトの名無しさん
垢版 |
2020/01/20(月) 15:15:43.28ID:0GX6odYx
once{};
みたいな構文で良いんじゃね
マクロとか書けば
2020/01/20(月) 15:21:36.51ID:hv8WW6TF
マクロ()
ベターCとか03で脳みそ止まってんだろうなw
452デフォルトの名無しさん
垢版 |
2020/01/20(月) 15:26:55.87ID:0GX6odYx
C++スレだからlambdaでも許されるけどCだと使えないやん?
2020/01/20(月) 15:29:38.41ID:hv8WW6TF
ほぉ、じゃあお前はCで使える文法のみでC++を書いてんだな
ボケてんのか?
2020/01/20(月) 17:52:26.33ID:SZK6NMcF
>>447
GOTO文有害説で言われる無条件分岐のスペルがbreakであろうとgotoであろうと同じことだ
同じ意味合いのことを書くために、ループでないものをループという嘘をつくことに俺は反対だ
455デフォルトの名無しさん
垢版 |
2020/01/20(月) 20:28:01.32ID:KSbNzMqr
結局、gotoは使わないほうが良いのですか?
2020/01/20(月) 20:51:28.03ID:SZK6NMcF
{ から } までを1命令と読めるようにするのにgotoは無用と言っているに過ぎない
そのようにまとめようとしていないときやgotoを使っても1命令と読める場合にまで
GOTO有害説に囚われ強弁するのは何も分かってないやつのすることということだ
2020/01/20(月) 20:56:48.81ID:rZl1icD3
つまんないことに拘りすぎ
どっちでもええがな
2020/01/20(月) 21:36:31.23ID:hWOi4sNW
>>448
今だとdo-whileでループする方が誤解の元になりそうな。
2020/01/20(月) 21:38:12.73ID:jzGRQ/VP
#define BLOCK(stmt) do { stmt; } while(0);

BLOCK(
if (error) break;
);
2020/01/20(月) 21:53:50.81ID:IuISEeYy
do{}while(0)とか初めて見たけど
ダサすぎてそりゃ思いつかねーわwww
2020/01/20(月) 21:55:40.09ID:dqQuCzGx
結局goto有害説に流されないオレカッケーが言いたいだけだろ?
それでもgotoが有効な場面なんかないけどな。禁止にしても問題なんかない。
2020/01/20(月) 22:00:17.76ID:SZK6NMcF
GOTO有害説に流されるのがオレカッケーと思っているようだな
アホwバカwww

禁止にしたら問題あるからlongjmpやthrowができてきたんだよ
463デフォルトの名無しさん
垢版 |
2020/01/20(月) 22:11:05.96ID:KSbNzMqr
つまり、使わないほうが良いのですね。
なんとなくですがわかりました。
2020/01/20(月) 22:12:08.37ID:SZK6NMcF
Javaから帰ってこなくていいからな
永久にバイバイ
2020/01/20(月) 22:30:44.49ID:dqQuCzGx
>>462
今時、例外の問題も把握してないでlongjumpとかthrowとか言ってんのか。。
馬鹿にもほどがあるわ。
負け確定だから泥仕合にしようってのはわかるがそろそろ引っ込めよ。
2020/01/21(火) 05:17:13.41ID:AnB6dumh
>>459
while(0)の後ろにセミコロン付けちゃダメ
2020/01/21(火) 07:25:59.02ID:XinnYwlJ
>>465
GOTO有害説に流されているという指摘は否定しないんだな?w
2020/01/21(火) 08:47:12.47ID:pAPT/+0o
>>459
定義部 { stmt; } のセミコロンも不要かな。
プリプロセッサを通した変換結果を見て気付いた。

って言うか、関数形式マクロの実引数に
空白とかカッコとかを含めることができるのね。
2020/01/21(火) 08:50:21.16ID:liyEgHWj
>>468
確かカンマも使えないはずだし、>>459のマクロは使い勝手は悪く制御構造も隠蔽する有害な使い方だろう。
2020/01/21(火) 09:35:24.55ID:ecU7KawI
gotoを使わないことが目的になって
余計分かりにくくしてるアホな例
2020/01/21(火) 09:49:43.57ID:Hkcle0K4
goto論争はくだらない
一方でラムダ使ったループ脱出は議論の余地がある
これがエレガントに見えるのか
パズルに見えるのか
自分の場合どちらかといえば後者
ラムダ自体は多用するけど
2020/01/21(火) 11:17:56.24ID:Sppu2iw7
盲目的にgoto=悪と信じて、かえって読みずらいコード書く奴ってほんとアホだよなあ
2020/01/21(火) 13:51:41.32ID:XinnYwlJ
>>470
ほんこれ
2020/01/21(火) 13:54:41.96ID:XinnYwlJ
gotoの何が悪いのかわかってないやつをもう少しいたぶってやろうと思ってたけど
途中で可哀想になってきて答え書いてやってるのになあ。。。
475デフォルトの名無しさん
垢版 |
2020/01/21(火) 18:52:44.87ID:xueGtX5x
>>460
do { } while(0)
は自分は見たことがある。
忘れてしまったが、確か、#define マクロの定義部分で使われていて、目的は、
マクロ全体が一つの分の用に実行されて欲しいことであったようだった。
#define マクロ名() do {\
・・・\
・・・\
} while(0)
のような感じだったと思う。

これなしで裸で書くより安全になる場合があった気がする。
2020/01/21(火) 18:57:29.70ID:fxsKQzaN
if (...) マクロ();
else ...
2020/01/21(火) 18:57:46.39ID:xueGtX5x
>>475
忘れてしまったが、おぼろげながら何か以下の様なことに関連していたような記憶がある。
C/C++では、if 文の直後は {}がなくても書くことが出来てしまう。
それで、
if (条件式)
マクロ関数名();
のように書いた場合、マクロの定義部を単なる {} で書くより安全な場合があったような
気がする。

忘れた。
2020/01/21(火) 19:00:56.98ID:xueGtX5x
>>476
あ、その場合だね、多分。
#define aaa() {・・・}
と定義してしまった場合、
if (...) aaa();
else ...
と書くと、
if (...) {};
else ...
と展開されてしまい、else の部分がエラーになってしまう。ところが、
#define aaa() do {・・・} while(0)
と定義していると、
if (...)
do {} while(0);
else ...
と定義されて、正しく動作する。
2020/01/21(火) 19:03:11.04ID:xueGtX5x
https://stackoverflow.com/questions/257418/do-while-0-what-is-it-good-for
↑に書いてあった。
2020/01/21(火) 19:11:44.38ID:jtyzl32v
それは11年前のネタだからそうなってるけど現代C++ならラムダ式で書くべき内容
2020/01/21(火) 19:19:17.16ID:fxsKQzaN
マクロでしか書けない物もあるんだよ
2020/01/21(火) 19:19:18.43ID:jXO8TLK9
大昔の工芸品みたいやな
2020/01/21(火) 19:24:51.40ID:fxsKQzaN
ていうかなぜラムダ式?
考える順は以下じゃない?

関数
インライン関数
テンプレート関数
マクロ
2020/01/21(火) 19:35:47.16ID:jtyzl32v
>>483
そこで回答されている
#define FOO(x) do { foo(x); bar(x); } while (0)

#define FOO(x) [&] { foo(x); bar(x); } ()
と簡潔に書ける
そのQAの内容は今のC++におけるdo-while(0)の有用性を示す内容ではない
2020/01/21(火) 20:01:36.85ID:fxsKQzaN
ああ、そういうことか

do while に対するメリットがないと
互換性から do while を選ぶことになりそう
2020/01/21(火) 20:17:22.53ID:V9u70PsA
ラムダ式はc++11からか
使えない環境は結構あるんだろうな
近付きたくない
2020/01/21(火) 20:20:59.68ID:m86EWX9f
>>484
最適化前提にしないと代替とは言えないね
2020/01/21(火) 20:21:55.39ID:OieZoAm+
そんな用途でマクロなんか使わねーわ。ばかか。
2020/01/21(火) 21:35:08.93ID:XinnYwlJ
スコープが効かねえ毒だかんな
2020/01/21(火) 22:01:33.56ID:fxsKQzaN
>>481
2020/01/21(火) 22:03:37.86ID:XinnYwlJ
__LINE__がいるのとかな
2020/01/22(水) 00:05:18.86ID:LIwEls05
>>484
JavaScriptだとそうかいても速度差がないかもしれないけど、C++だと、
そう書いた場合は、関数を定義してから、マシン語の call 文でその関数が
呼び出されるので結構なオーバーヘッドとなる。
JavaScriptの場合は、どう書いてもオーバーヘッドがあるからそのくらいの
オーバーヘッドは体感速度に登ってこないのでどっちでも良いだけ。
2020/01/22(水) 00:20:06.55ID:2biZgMt+
>>492
ラムダ式はインライン展開されるからオーバーヘッドにはならない
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。