C++相談室 part136
■ このスレッドは過去ログ倉庫に格納されています
次スレを立てる時は本文の1行目に以下を追加して下さい。
!extend:on:vvvvv:1000:512
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。
前スレ
C++相談室 part135
https://mevius.5ch.net/test/read.cgi/tech/1522495206/
このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.102【環境依存OK】
http://mevius.5ch.net/test/read.cgi/tech/1509780815/
■長いソースを貼るときはここへ。■
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 >>248
俺から見ればお前がキチガイだし、
ここがお前にとって合わないと思うのなら、お前がここに来るのが間違ってる。
ゆとりはゆとりだけでスレ作れよ。
それがお互い一番幸せな解決だ。
俺には韓国人とゆとりは殺すしかないという結論が出てる。
お前らは邪魔しかしないから。今もそうだろ。 初心者で的はずれな質問かもしれませんがお願いします。
1行に約4000文字,区切りで書かれたファイルがあり、これが1000行あります。
このファイルを1行ごとに別の配列に格納したいのですがfgetsだとchar型になりcharは256文字しか入らないようです…
どうしたら読み込みできるのでしょうか >>250
> fgetsだとchar型になりcharは256文字しか入らないようです
単に間違えたプログラムを書いている。
そのプログラムを提示してみて。 C言語を通らずにいきなりC++を使う初学者は
fgetsやcharに触れるべからず
必ずラッパーライブラリを使うべし >>250
getcを使ってmyfgetsを新たに作る
改行を調べるだけなのでそんなに苦ではない >>247
C++風に考えるとstd::shared_ptrは必要なくなってくるけど、他の言語の真似をしようとすると、必要になるんだよな。
そしてC++は他の言語から呼び出されるから。
そういう部分で必要があるのかも。 スレッド使う場合は、コピーのほうが速くないかよく考えた方が良い。
意外とコピーのほうが速い。 >>253
宗教じみたことは言わないほうがいい。
C++の入出力クラスiostream系の標準機能は失敗した代物との結論が出ている。
C++学習者は FILE* 系の標準機能を優先して使うのが正道。 >>257
iostream 系のどんなところが失敗しているのですか? >>257
あり得ない
ポインタも分からん奴に生char使われてたまるか
fgets使いたいならC言語で基礎を身に付けてから出直して来いや たしかにiostreamはデストラクタで自動的にクローズしてくれるくらいしか
メリットが感じられないから、自分でファイル入出力クラス作ってるわ iostreamはC++のテンプレートクラスが未発達だったころの遺物だよ。STLに含まれない時点でお察しではあるが。
iostreamを使うよりもshared_ptrなどのスマートポインタでFILE*をラップしたテンプレートクラスを使うほうが現代的。
shared_ptr::shared_ptr<FILE>のコンストラクタで第二引数にfclose()を呼び出すdeleterオブジェクトを渡すだけで事足りる。
shared_ptr::shared_ptr<FILE>直使いもいいが、その派生クラスを使って暗黙のFILE*型キャスト演算子を実装すれば、Cコードとの移植性がさらに高まる。
あと、iostreamはios系の様々なフラグがあるが、煩雑で使い勝手が悪い。覚える価値ゼロ。 >>258
速度じゃないか?
使いもしないオペレータのために余計な処理挟むから。
VCについてくるディンカムウェアなんか一バイトごとに仮想関数呼び出してるぞ。 訂正。
shared_ptr::shared_ptr<FILE> じゃなくて、shared_ptr<FILE>でした。
deleterサンプルは以下の通り
struct file_deleter { void operator() (FILE* fp) const {if (fp != NULL) { fclose(fp); } }};
shared_ptr<FILE> fp(fopen(filename, "r"), file_deleter());
// 以下、fp.get() でFILE*にアクセス。 まあでも、明らかな失敗だったら auto_ptr や wstring_convert みたいにとっくに deprecated にされてるよね。 class FILE_Ptr : public ns_shared_ptr::shared_ptr<FILE> {
struct FILEDeleter {
void operator() (FILE* fp) const {
if (fp != NULL) {
fclose(fp);
}
}
};
public:
FILE_Ptr(FILE* fp = NULL) : ns_shared_ptr::shared_ptr<FILE>(fp, FILEDeleter()) {}
operator FILE* () { return get(); }
template<typename T> bool operator == (const T& obj) const { return get() == reinterpret_cast<FILE*>((void*)((intptr_t)obj)); }
template<typename T> bool operator != (const T& obj) const { return get() != reinterpret_cast<FILE*>((void*)((intptr_t)obj)); }
};
void fclose(ns_shared_ptr::shared_ptr<FILE>)
{ >>266を途中で送信してしまった。
ns_shared_ptrは、boostなりstdなりstd::tr1なり自分の好きな名前空間に置き換えを。以下のように。
namespace ns_shared_ptr = boost;
グローバル関数fclose(ns_shared_ptr::shared_ptr<FILE>& fp)を別途作れば、
Cのコードをコピペ利用した時のfclose(fp)多重呼び出しを防止できる。 >>207,208
>>255,256
DOMの話か?500MBは言い過ぎだからとりあえず放置したが、
GC言語は基本的にshared_ptrの仕様だから、その実行エンジンの実装に使われるのは妥当だ。
これをサポートする為、shared_ptrは仕様上は必要だ、というのも同意する。
問題はそれがデータ構造として必要か、という点で、
DOMの場合、HTMLは共有無し/循環参照無しの単純な木だからunique_ptrだけで問題なく構成出来る。
ただしJavaScript側に捕まれている場合、ノードが木から取り除かれた場合にも保持し続けねばならず、
この実装にはshared_ptrを使わないと厳しいだろう。
しかしこれはデータ構造ではなく、JavaScriptの仕様が原因だ。
マルチスレッドのキャッシュについては、これは現時点でのハードウェアの問題で、
単純に言えば共有RAMに対して書き込みをすれば著しく遅くなるだけだ。
これはデータ構造の問題ではないので別に取り扱う必要がある。
(速度低下はshared_ptrの問題ではなく、キャッシュ構造起因)
データ構造について言うなら、shared_ptrの使いどころは、
1. 共有ノードがある
2. 循環参照はない
3. 動的に生成/消滅を頻繁に繰り返す
だと思うんだが、2の為にメッシュ構造とかは基本的にアウトで、
3も基本的にないだろ。
実はあんまり使いどころなくね?って話。 weak_ptr の使いどころを見極めるのが難しい。 >>261
>iostreamはios系の様々なフラグがある
そうそう、今いち、よく定義がわからないんだよね
それに、手元の実装がこのフラグについてまともじゃないかもしれない iostreamを今、作り直すとしたらfilesystemやstring_viewも視野に入れなきゃね C++でよく使われる各オブジェクトのスタックサイズは以下の通り。
stringstreamとfstreamのサイズは無視できない大きさであることがわかるだろう。
・GCC - ubuntu Linux x64
(sizeof(std::stringstream), sizeof(std::fstream), sizeof(std::ostream), sizeof(std::string), sizeof(std::vector<std::string>), sizeof(FILE))=(392, 528, 272, 32, 24, 216)
・Visual Studio 2017 - Windows10 x64
(sizeof(std::stringstream), sizeof(std::fstream), sizeof(std::ostream), sizeof(std::string), sizeof(std::vector<std::string>), sizeof(FILE))=(248, 280, 112, 32, 24, 8) >>273
数百バイト程度は許容できるんじゃないの。
コンテナに入れるわけでもないし。 直近のスレを見れば分かるとおり、C++は複雑怪奇魑魅魍魎だから
プログラミング初学者が手を出したらヤケドしかしない 勉強でヤケドする分には問題ないし、
むしろ沢山ヤケドして危険を避ける能力を身に着けるしかない。
実務でやったらアウトだが。 iostream 文句言われてるけど、atomic に動作するところは thread 並列環境では
そこそこ良いのでは?もちろんその分遅さが気になる場面もあるけど。 iostreamは速度を全く期待せずに使うという
C++らしからぬ面を持ったものだ
sync_with_stdio? はははは 国際化に向かないのが致命的。
これだけで捨てる理由としては十分と思う。 MSVCのstd::arrayがC++11に準拠してくれればいいのに。使えねー。
言語レベルで区間チェックしてくれたら、データ破壊の場所がすぐにわかるのに。 スタティックライブラリAが別のスタティックライブラリBのAPIを使っている場合、ライブラリAにライブラリBをリンク、ビルドして、結果できたライブラリAだけをリンクして、実行ファイルを作る形式が良いでしょうか。
それともラリブラリA、ライブラリBを別々にリンク、ビルドして実行ファイルを作る形式が良いでしょうか。 >>282
>ライブラリAにライブラリBをリンク、ビルドして、結果できたライブラリ
そんなことができるのでしょうか? >>281
msvcのat()関数は範囲チェックしないの? iostream の替わりになるようなデファクトスタンダードが登場していない以上、
ほどほどに付き合っていくしか仕方がないよ。
C スタイルは普段から使うには抽象度が低くて面倒くさい。
printf は std::string を表示するのにさえいちいち c_str を通さなきゃならんのだからな。
書式指定との整合が型システムで保証されないのも古い設計だし。
処理系の方である程度は特別扱いすることで折り合いがついてるけど、
あらためて考えるとだいぶん不格好だと思う。
コンセプトやら何やらが導入されたらもうちょっとマシな入出力ライブラリが出来たりしないもんかね?
提案くらいは出てたりしない? って思ったけど、こないだ江添っちがTwitterで「無い」って言ってた気がする。 現実的にはxmlなど標準的な形式のファイルを扱うライブラリを使うんで本当に低レベルなIOはどっちでもいい >>274
iostreamは肝心な時に使えない橙武者です。
ログ出力するクラスは歌舞伎の黒衣のような慎ましい存在でなければならないのですが、
iostreamはあたかも歌舞伎の花形役者のようなオレ様的存在感を出すので好ましくありません。
実例をあげるならば障害発生した時に、ログ用途でiostream系を使うことがあり得えます。
cout やその他インスタンスが生成されてスタックを多く使うことになります。
つまり、実運用環境とログ埋込環境でメモリ構成が大きく異なる環境になってしまうことが避けられません。
iostreamはマルチスレッド環境など対話デバッグでは追跡しにくい現象をログ出力するのに適さない、と断言できます。
橙武者、黒衣など語の意味が分からない方は、ご自身でおググり下さい。 coutってアクセスするたびに生成するわけじゃないよね? ツリートラバースするのに、再帰使うよりstd::deque使ったスタックのほうが速いな。 >>291
グローバルオブジェクトとしてずっと存在してる 内緒ですけどね。書式設定はprintfのほうがソースが見やすいですよ。 「標準出力への書き込みは遅いから」との理由で、メモリ上にログをため込むことは多いかと思います。
iostream系だと stringstreamを使うことになりますがスタックサイズが割と大きくインスタンス生成のたびに時間もかかります。
さらにいえば、MSVCの場合、snprintf()に比べてstringstreamは書き込みに3倍弱時間がかかります。
本来ならば << 演算子はコンパイル時に型が決まるので書き込みが高速なはずなのですが、
MSVCだとstringstreamがsnprintf()に負ける有様ということです。
なお、Linux GCCの場合、snprintf()とstringstreamは書き込み速度の差は少ないようです。 CとC++で演算子の優先順位が異なる所があります
どこてしょう
もちろん両方に存在するものです >>298 の問題は面白いし俺も答えに興味あるけど >>297 への挑戦とすれば
「C++は完全に理解したけどCの方は知らないよ」で逃げられるかと。 C++の規格はCの規格を参照してるし、Cとの差異も規格の一部になってるので
C++の完全な理解の中に当然含まれる アホなので優先順位の違いはわからないけど、
if ((v=f()) == 0) を if ((v=f()) = 0) とタイポしたとき
c++ だとエラーにならず v が 0 になるのは嫌な感じ if ( 0.equals(v=f()) )
こう書ければいい Cでは代入式はその結果値が左辺値にはならないから v = 1 = 2 みたいな表現は通らない
C++では左辺値になるので通る 昔定数を先に書くことで防げるって聞いたことがあるが
0=(v=f()) 昔からこういう==での判定は
if (S_OK == (result = someApi()) {...}
と定数左で書けという作法もあるけど、
流行らないのは見た目が実行順と逆みたいで妙だからかねえ 〇〇=0 はあるけど 0=〇〇 は違和感しかないからなぁ
バッドノウハウの筆頭だと思う 数学でも 0 = x^2 + 3x - 2 とかあまり書かないな まあそんなクソな書き方するくらいならテストコード書けやって話にはなるわな。 >>304-305
それいつの話だ馬鹿野郎
俺が新兵の頃には、そんなコード書いたら教官からブン殴られてたぞ!! バッドノウハウ……かなぁ…?
定数を左に書く利点は テストより手軽にコンパイルエラーで止められる事だから
個人的には採用してるんだけど
int i = 0;
/* 想定した挙動 */
if ((i = 0) == 0) { printf("%i\n", i); } /* 定数 右: 出力 "0" */
if (0 == (i = 0)) { printf("%i\n", i); } /* 定数 左: 出力 "0" */
/* typo! == -> = */
if ((i = 0) = 0) { printf("%i\n", i); } /* !!! printfが実行されない! (Cでは通らない) */
if (0 = (i = 0)) { printf("%i\n", i); } /* コンパイルが通ら*ない* 助かった! */
/* () 忘れ */
if ( i = 0 == 0) { printf("%i\n", i); } /* !!! 出力 "1" (== (0 == 0) == true) 想定外! */
if (0 == i = 0 ) { printf("%i\n", i); } /* コンパイルが通ら*ない* 助かった! */
そもそも1文字の打ち間違いなんて テストコードの記述そのものでもやりかねないし
(「絶対に間違えない!」なんていう人がいたらコードどころか作文も書いたことない奴ですぜ)
まあ使用が推奨/禁止されてるかはチームに従うとして
ぱっと見で意図が解るようにはしておくとよいかと >>310
そういうのはもはや統合開発環境の仕事なのだよ。
ていうか if の中で代入を書くとか真正のキチガイ。
有 り 得 な い すまんかった >>303 は "v = 1 = 2 みたいな" ではなくて "(v = 1) = 2 みたいな"
括弧忘れたら結合順が変わってしまう 訂正 EmacsのせいでUNIXはDOSに負けたんだっけ。 単体テスト書くと処理時間出るから、何に時間かかってるのかわかっていいよね。 やはり一番時間がかかるのはIOだから、IO少なくするのが一番よさそう。
std::vectorなんか全体コピーしても余裕の速さだから気にする必要なかったんや。 世の中いろんなコーディングルールがある
ifの中は副作用のあるコード禁止とか
goto禁止とか
3項演算子禁止とか
1個の関数は○○行以内とか
変数名は○○文字以内とか
実際に業務で書かない人が決めたりするからたちが悪い if の条件式の中で代入することは勧められない書き方だと思うけど、
「言語仕様に照らして完全に正しいけど間違いやすい書き方」にいちいち警告を出されるとうんざりする。
オプションで強めのチェックにしたときならともかく、デフォルトでだぞ。
かといって個別に警告の有効・無効のオプションを書くのも面倒くさいしなぁ。 俺も定数との比較なら
if ( 0 == buf )
って定数を左に書くようにしてる
理由は>>310と同じ意図しない代入防止 自動的に静的チェックツールかけとけば教えてくれるよ 関数の戻り値を保存した一時変数を使わなかっただけで警告出されるのは地味につらい。かといって警告を抑止するのも悩ましい。
以下のような感じ。
void test()
{
int foo = bar();
return;
} じゃなくて・・・、BARのreturnにブレークポイントだ。
VSのばあいだけど。
そんな出口の多い構造で大丈夫か。 よくわからんのだが使わんものをなんで残しとくのん? >>326
戻り値ありということは普通は副作用なく作るだろ
その戻り値を無視したら計算資源だけ使って何もしないってことだよ
なんのためのコードなのそれ? 副作用ありの関数で成功失敗その他を戻り値で返すのはごく普通にあることでは。 このスレは、「風邪をひいたんだがどうしたらいい?」との相談に「風邪をひくな」と真顔で回答する良スレですね。 相談する時は、「なんでそんなところ行ったんだ」などと“そもそも論”を始めて責任所在の確定に情熱を傾ける後ろ向きで生産性ゼロの人に相談することは避けなければならない。
これが私の設問の真意。以下が回答。
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\ItemTemplates\VC\Windows Store\1041\BasicPage\BasicPage.xaml.cpp:97
(void) sender; // 未使用のパラメーター Visual Studioなら不要な警告を非表示に出来るだろ >>324
if (buf = 0) {
}
を検出するためのテストってどんなものですか? 補足すると、マクロ定義によって戻り値が使われなくなることがある場合の警告を想定。
>>336 であげた BasicPage.xaml.cppの事例は厳密には関数の仮引数を使わない場合の警告なので若干違うが、対処法は同じ。
#define OUTPUT(x)
void test()
{
int foo = bar();
OUTPUT(foo);
(void)foo;
return;
} >>339
そのコードにエフェクトがあるならテストできるのではないでしょうか。 >>339
そういうのはコンパイル時にWarning出るから本線にマージする前には見つかるでしょ 変数で戻り値を受けとって使わないって言うのは確かに変だが
戻り値がある関数の戻り値を受けとらないって言うのは問題無いのか? >>342
>>339 に対する具体的なテストの方法を示してください >>345
それ単体テストやればカバレージ100%にならないから容易に検出できるだろ >>340
最初に書いとけよタコが
お前の想定など知るか >>339
if (buf = 0) { A }
・buf がゼロの時 A が実行されないと実行結果(出力など)が正しい結果にならない場合
・bufが非ゼロでここでゼロにされると以下同文
この2つの場合は結果がおかしいからテストで見つかる。
結果は正しいが見つけにくいリークが発生するとか
ここ間違えても結果は(常にではないが)多くの場合正しい
とかだと静的/動的カバレッジで見るしかないね。 ■ このスレッドは過去ログ倉庫に格納されています