0からの、超初心者C++相談室
1 :デフォルトの名無しさん :2018/11/12(月) 14:55:13.35 ID:Tf74ZWQr.net 何にも知らない0からの出発、超初心者のためのC++相談室
729 :728 :2023/12/12(火) 14:02:16.36 ID:haJQSzRG.net エラーは何もなくて変数に何も格納されてない状態だったので原因よくわかりませんでしたが 今回は>>728 さんの言う通りになっていて解決できました まだmsys2自体の仕様も十分に理解してなくて手が回っていない状態なのでこれでいったん失礼します ありがとうございました!
730 :デフォルトの名無しさん :2023/12/12(火) 15:14:22.81 ID:bMo3JLCK.net GUIから起動するとカレントディレクトリがホームになるんだったっけ?
731 :デフォルトの名無しさん :2023/12/13(水) 15:23:50.85 ID:Xh1qTD5r.net OSの事情でカレントが簡単に移動してしまうのがめんどいな
732 :デフォルトの名無しさん :2023/12/13(水) 16:17:33.78 ID:b3+IUHNQ.net プログラムの実行に必要な設定ファイルやデータファイルはカレントディレクトリではなく実行ファイルのパスを基準に決めたほうがいいね
733 :はちみつ餃子 ◆8X2XSCHEME :2023/12/13(水) 17:12:54.61 ID:vPv7AHCs.net 設定ファイルの類いは AppData フォルダに置くのがこのましいということになってる。 アプリケーションインストール用のフォルダ Program Files は書き込み権限が制限されているからそこに設定ファイルは置けない。 逆にどうしてもアプリケーションと設定ファイルを同じフォルダに置きたいなら Program Files にはインストールできない。 Msys2 内で使うソフトならホームディレクトリ (windows のホームディレクトリではなく msys2 が設定するホームディレクトリ、環境変数 HOME で取得できる) に設定ファイルを置くのが基本的な習慣。
734 :デフォルトの名無しさん :2023/12/13(水) 17:14:51.41 ID:Xh1qTD5r.net 起動時の引数や 自分のフルパスを取得するAPI経由で 実行ファイルのある場所を基点にどうこうすることが多いわ (Windows unix だと usr と bin で分ける文化があるからそういうのはどうなってるんやろか 起動時のカレントのまま?
735 :デフォルトの名無しさん :2023/12/13(水) 17:20:10.83 ID:b3+IUHNQ.net >>733 それはインストーラー使うアプリでしょ? XCOPYインストールアプリの話だよ
736 :デフォルトの名無しさん :2023/12/13(水) 17:23:03.86 ID:HyXW4bJ5.net カレントじゃ無くて、アプリが実行されたディレクトリに一緒に置いとくもんだろ? ユーザー毎に違う設定にしたいなら、各ユーザーのホームディレクトリだろ?
737 :はちみつ餃子 :2023/12/13(水) 18:03:20.75 ID:vPv7AHCs.net >>736 基本的にはそうだけどパッケージマネージャの管理方式との相性があったりする。 scoop で管理するなら設定ファイルも含めてひとつのフォルダに入れるほうが都合が良いと思う。 Msys2 内で pacman で管理するなら unix 風の流儀のほうが自然だし。
738 :デフォルトの名無しさん :2023/12/13(水) 23:12:49.25 ID:zjCiNOvz.net グローバル位置に宣言したオブジェクトはmain前にコンストラクタが実行されますね。 仕様ではmain前に実行ということのほかに何か規定はありますか。 ある処理系で、main先頭である処理を呼び出すと成功するが、その処理を上記のコンストラクタから呼び出すと失敗するということがありました。
739 :はちみつ餃子 ◆8X2XSCHEME :2023/12/14(木) 00:23:02.09 ID:GWgG2Hfk.net >>738 ややこしい規則が色々あってここには書ききれないがおおざっぱにはこんな感じかな。 ・ 定数初期化が終わってから動的初期化がされる ・ 動的初期化でも条件が揃ったときは静的初期化扱いで早めに初期化する最適化をしてもよい (しなくてもよい) ・ 翻訳単位内の初期化順序は定義が現れた順序 ・ 翻訳単位をまたぐとどちらが先に初期化されるかは規定されていない 特に翻訳単位を跨いだら決まってないってのは引っかかりがちなポイントで、 強い依存関係のあるものはあまり細かく分割しないほうがやりやすいと思う。
740 :デフォルトの名無しさん :2023/12/14(木) 01:04:36.74 ID:X6Ol8Z5z.net 普通は、WSL2 でLinux を使う MSYS2/MinGW の利点は、 hypervisor で、2つのOS を起動しないから軽い WSL2 では、Linux側から、Windows 側のアプリも起動できる。 ただし例えば、powershell ではなく、powershell.exe と拡張子も付ける 例えばpowershellで、Windows側のフォルダ内の一覧を表示して、Linuxのgrep で絞り込む /mnt/c/Users/ユーザー名/Documents$ powershell.exe ls | grep クイ 出力 d----- 2015/10/13 13:52 クイズ VSCode の拡張機能・Code Runner は、 右クリックメニューから、選択したコード、またはファイル全体を実行する この設定をチェックしておく Code-runner: File Directory As Cwd Whether to use the directory of the file to be executed as the working directory. そうすると実行時にcd で、そのファイルがある場所へ、カレントディレクトリを移動してから、 そのファイルをコンパイルして実行する 設定項目、executorMap には、多くの言語の実行コマンドが書いてある。 "code-runner.executorMap": { "c": "cd $dir && gcc $fileName -o $fileNameWithoutExt && $dir$fileNameWithoutExt", "cpp": "cd $dir && g++ $fileName -o $fileNameWithoutExt && $dir$fileNameWithoutExt",
741 :デフォルトの名無しさん :2023/12/31(日) 22:48:46.98 ID:tpduSr4A.net 相談室から誘導されたのでこちらで http://mevius.5ch.net/test/read.cgi/tech/1698705458/104 buf_にPODではないオブジェクトが含まれる可能性がある場合、この領域をどのようにcopyしたりmoveすればよいでしょうか?
742 :デフォルトの名無しさん :2024/01/01(月) 01:29:30.25 ID:/rCM9JK/.net このスレッドはゼロからC++と言っているが、C言語を知っている前提になっているよなw
743 :デフォルトの名無しさん :2024/01/02(火) 11:00:49.80 ID:TDOOgc4U.net ワシも割と長く底辺コピペプログラマだけどなんでそんな詳しくなれるの?ってなる 有能と俺みたいな無能はどこでプログラマの生き方をたがえたのか
744 :デフォルトの名無しさん :2024/01/02(火) 20:21:16.21 ID:G9bvfkvl.net >>743 頭の出来で決まっているからね 義務教育レベルで脱落した人間、日本語能力に問題がある人間は、プログラマーとしても問題がある。
745 :はちみつ餃子 :2024/01/02(火) 21:40:20.68 ID:RkRzwbey.net 知識は入れないと増えないというすごく当たり前の話。 長く放置してたら勝手に増えるなんてことはないよ。
746 :デフォルトの名無しさん :2024/01/03(水) 08:18:02.54 ID:3n4RUKo6.net ガキの頃からマイコンBASICマガジン見てたけど PCなかったしポケコンはあったからたまにあるポケコンゲームのソースをポチポチ入力してたけどそれで何かの知識になったか言われたら何にもならんかったな
747 :デフォルトの名無しさん :2024/01/03(水) 08:26:31.48 ID:uKn1SmuA.net 糞コテが
748 :デフォルトの名無しさん :2024/01/03(水) 13:07:46.32 ID:3mJitcl/.net >>746 SHARPのポケコンでマシン語使ってシューティングゲーム作ったけど?
749 :デフォルトの名無しさん :2024/01/03(水) 13:17:11.92 ID:SgwYv7hO.net ポケコン触ってたころが一番楽しかったです 手の中に物理キーボードと実行環境があるんだもん 一生遊べるよ
750 :デフォルトの名無しさん :2024/01/03(水) 14:56:53.56 ID:giTORTIB.net >>741 memcpyでなくちゃんとplacement newでコピーorムーブコンストラクタ走らせればいんじゃね?
751 :デフォルトの名無しさん :2024/01/10(水) 03:00:04.91 ID:lNNg6PiH.net Class Hogeの中でたくさんのFugaを管理するために std::vector<std::unique_ptr<Fuga>>というメンバ変数を作りました 可変長引数テンプレートで複数のstd::unique_ptr<Fuga>を受け取るコンストラクタを書こうとしたのですが std::unique_ptrがコピー禁止のためうまくいきませんでした。 Hoge(Args&&... args) という形で右辺値参照を受け取ってうまいことムーブしてClass Hogeを初期化する方法ってありますか?
752 :はちみつ餃子 ◆8X2XSCHEME :2024/01/10(水) 04:36:30.64 ID:BOjhYgCx.net >>751 できると思うけど、何をやりたくて何が上手くいかなかったのかイマイチわからない。 出来なかったコードをみせて。
753 :デフォルトの名無しさん :2024/01/10(水) 11:27:22.10 ID:lNNg6PiH.net >>752 class Fuga { int placeholder; }; class Hoge { public: std::vector<std::unique_ptr<Fuga> > vec; template<class... Args> Hoge(Args... args) { vec = {args...}; } }; int main() { /*Fugaを何個か作成*/ auto p1 = std::make_unique<Fuga>(); auto p2 = std::make_unique<Fuga>(); auto p3 = std::make_unique<Fuga>(); /* 中略 色々処理 処理が終わったらHogeの中にFugaをまとめて放り込みたい*/ Hoge hoge(p1,p2,p3); } こういうものを書いたらunique_ptrがコピー禁止でエラーになったのでムーブにしたいけど書き方がわかりませんでした。
754 :はちみつ餃子 ◆8X2XSCHEME :2024/01/10(水) 12:45:18.04 ID:BOjhYgCx.net >>753 この場合は initializer_list が問題。 initializer_list を経由するとムーブ可能/コピー不可な型を扱えない。 initializer_list を経由しない形にすればよいので要素を emplace_back で 入れる形にするなどの対処法が考えられる。 #include <memory> #include <vector> class Fuga { int placeholder; }; class Hoge { public: std::vector<std::unique_ptr<Fuga> > vec; template <class... Args> Hoge(Args&&... args) { (..., vec.emplace_back(std::forward<Args>(args))); } }; int main() { /*Fugaを何個か作成*/ auto p1 = std::make_unique<Fuga>(); auto p2 = std::make_unique<Fuga>(); auto p3 = std::make_unique<Fuga>(); /* 中略 色々処理 */ // std::move で右辺値にキャスト Hoge hoge(std::move(p1), std::move(p2), std::move(p3)); }
755 :デフォルトの名無しさん :2024/01/12(金) 09:52:36.06 ID:Umd8uX9b.net c++で日本語の連想配列ってあります??
756 :デフォルトの名無しさん :2024/01/14(日) 15:30:33.22 ID:O4q5V5KL.net >>755 std::mapじゃだめなん?
757 :デフォルトの名無しさん :2024/01/16(火) 21:37:05.24 ID:eUaXJLuy.net >>754 無事に動作させることができました。ありがとうございます!
758 :デフォルトの名無しさん :2024/01/20(土) 18:17:15.80 ID:9qysS+ur.net 時間のかかる処理があり、それが現在のスレッドをブロックして欲しくないので その処理の部分に関してstd::async()の利用を検討していますが、 これって戻り値(future 型)でモニターしないといけない感じですか? 上記の処理はいつ終わるかは気にしないので別スレッドに投げっぱなし?で構わない のですが... pthread_detach()的な?
759 :はちみつ餃子 :2024/01/21(日) 12:43:25.73 ID:4rk7TZPC.net >>758 std::thread のメンバ関数に detach はあるけど、期待するのはこういうこと? ただ、メインスレッドが終了すれば他のスレッドが稼働中でもプロセス終了処理に入るし、 プロセス終了処理の中で標準ライブラリの後始末している最中に他のスレッドが 標準ライブラリを使うようなことがあると破綻するかもしれない。 強引に終わらせて良いなら std::quick_exit で即死させるという方法も取れるが、 基本的にはプログラムを終わらせるときには全てのスレッドを終了させて (終了を待って) おくのが 普通だと思う。
760 :デフォルトの名無しさん :2024/01/21(日) 21:48:26.38 ID:zlvjOB5M.net >>758 ですが、お返事ありがとうございます。 はい、とりあえず thread::detach() を使うようにしました。1つの疑問は、 https://ja.cppreference.com/w/cpp/thread/future/~future によると > ただし、その共有状態が std::async によって作成され、まだ準備完了になっておらず、これがその共有状態への最後の参照である場合は、ブロックする可能性があります。 ええ何それ、というのが発端でした(後出し失礼)。 確かに、メインスレッドの終了時のこともありますし、スレッドの後始末をちゃんと した方が本当はいいように思われます。処理が長時間たっても終了しない場合 タイムアウトさせたりとかも。 何かシステマティックな方法等あるでしょうか。参考になるものがあれば...
761 :はちみつ餃子 :2024/01/22(月) 12:54:36.50 ID:T1sqP3ZB.net >>760 メインスレッドの終了直前でまずは適当にフラグを立てた上で他のスレッドの終了まで待機する。 重い処理をしているスレッドの側で完了ではないにしても区切り良く終われるポイントでフラグを読んで フラグが立っていれば後始末ルートに入ってスレッドを終了させる。 その結果としてメインスレッドの待機状態が終わってプロセスの終了。 というのが普通の大まかな流れだと思う。 その上で待機時間があまり長すぎるようだと強引にでも終わらせるとかの処理を入れるかも。 std::async は既存の関数を非同期化するちょっとしたユーティリティという立場なんじゃないかな。 それで事足りるときは便利で簡単だけど、細かい制御を勝手にやってくれるわけでもないし、 やろうとするとちょっとイマイチって感じ。
762 :デフォルトの名無しさん :2024/01/28(日) 11:52:43.80 ID:W0uCnQb3.net 質問なのですがどんな環境(ロケール設定)のPCで動かしても 数値や時刻の入出力を修飾無し(12345 が 12,345 になったりしない)にする完璧な方法って次の3行で良い? setlocale(LC_ALL, ""); // printf()、scanf()に反映 _wsetlocale(LC_ALL, L""); // wprintf()、wscanf()に反映 (※ 環境依存。左記はWindowsの場合 std::locale::global(std::locale("", std::locale::all)); // cout、wcout、cin、wcin、ostringstream、wostringstream、...etc. C++の全部に反映 あとなんか実験する限り cout.imbue(std::locale("")); std::locale::global(std::locale("", std::locale::all)); とするとcoutが修飾有りとなり、cout.imbue()で与えた設定をstd::locale::global()が上書きしないように見えるのですがそういうもの?
763 :はちみつ餃子 :2024/01/28(日) 13:12:39.75 ID:hRRbWEE/.net >>762 言語仕様通りならそれらの関数を呼び出さないようにすれば環境に固有の表現の変換はしない。 std::setlocale の設定が C の標準関数の挙動に影響するのはその通り。 ただし、様々な環境での「同じ動作」を期待するなら "C" を与えるべき。 空の文字列を渡した場合には環境に固有の設定であり、通常はシステムの設定が反映される。 プログラムは起動したときに setlocale(LC_ALL, "C"); 相当の状態なので、普通は書く必要もない。 std::locale::global での設定は C++ の標準ライブラリの挙動に影響するだけでなく std::setlocale での設定にも反映されるので両方を呼び出す必要はない。 これもプログラム起動時のロケール設定は "C" 相当になっているのでそれで良ければ呼び出す必要もない。 ただし、 std::locale::global に与える設定が名前を持たない場合 (つまり std::locale("") のような場合) は std::setlocale 相当の変更もするかどうかは規定されない。 imbue はストリームにロケールを結びつけるのでグローバル設定とは独立して機能する。
764 :デフォルトの名無しさん :2024/01/28(日) 14:11:55.68 ID:eBJAlicu.net クラスオブジェクトの代入文に、=による単純コピーと、=演算子関数による独自コピーのどちらを使うか迷います。 たとえばメンバ変数が基本データ型の集まりなら単純コピーでいい。 今出くわしたのはメンバ変数がstd::array<int, 3>の場合で、まあたぶん単純コピーでよさそう?じゃあstd::vector<myclass>なら?などと疑問が深まります。 あとコピーコンストラクタによる初期化も合わせて考える必要がありそう。
765 :はちみつ餃子 :2024/01/28(日) 14:36:51.31 ID:hRRbWEE/.net >>764 単純コピーってのは何のこと? デフォルトで生成される代入演算子の意味で言ってるのかな?
766 :デフォルトの名無しさん :2024/01/28(日) 15:36:35.20 ID:W0uCnQb3.net >>763 レス㌧クス、 >ただし、様々な環境での「同じ動作」を期待するなら "C" を与えるべき。 なるほど "C" ですたか、これか↓ https://www.ibm.com/docs/ja/zos/2.2.0?topic=utility-locale-naming-conventions >普通は書く必要もない。 実はウィンドーズでUnicodeで出力する場合限定かもですだが、ロケール設定しないままだと 日本語OSでも漢字が表示されなかったり(L"Hello World! 漢字" → 表示: Hello World! ) 英語OSに持っていったら L"Hello World! 漢字" が丸ごと出なかったり……orz まあ漢字はこの際どうでも良いので、ロケール設定 "C" で行こうと思いまつ
767 :デフォルトの名無しさん :2024/01/28(日) 16:37:46.15 ID:eBJAlicu.net >>765 そうです。
768 :はちみつ餃子 :2024/01/28(日) 16:38:46.52 ID:hRRbWEE/.net >>766 Windows での話か……。 msvcrt だとどうにもならなくて ucrt でちょっとマシになってるみたいな話題をこないだ Teratail で見たぞ。
769 :はちみつ餃子 :2024/01/28(日) 16:52:54.16 ID:hRRbWEE/.net >>767 デフォルトで生成される代入演算子は全てのサブオブジェクト (基底とデータメンバ) を 代入演算子でコピーするのと同じ挙動になることになってる。 基底やデータメンバが適切に代入演算子を定義されているのならデフォルト生成にまかせてよいことが多い。 注意を払う必要がある典型的なものは生ポインタで、 ポインタをコピーしても指してる先のオブジェクトはひとつだから そのへんの扱いはデフォルト生成だとあかんことになる。 あとは外部のリソースと結びついているオブジェクトだと単純にコピーできないか、コピーさせないこともあるな。 分かりやすい例で言うなら std::thread なんかはスレッドを抽象化したものだけど オブジェクトをコピーしたらスレッドもぽんぽん増えるなんてことになっても困るし スレッドひとつに対応しているオブジェクトがいくつもあるようでも困るのでコピーできないようになってる。 それぞれに事情があるので明瞭な判断基準があるわけじゃないけど、 デフォルト生成の結果がほんまに自分の意図通りに動作するか考えてみて あかんなら自分で書くしかない。
770 :デフォルトの名無しさん :2024/01/28(日) 17:03:17.17 ID:eBJAlicu.net >>769 いつもありがとうございます。 たいていはデフォルトでよさそうですね。 std::vectorは可変長配列ってことなので、<int>であってもデフォルトでいいのかなと心配に…あこれはvectorのほうで独自=定義されてるなら問題ないわけですね。
771 :デフォルトの名無しさん :2024/01/30(火) 20:47:22.29 ID:RcbbllHt.net bだけ通らないのが納得いかない…。 #include<iostream> #include<functional> using F = std::function<void()>; void f0(){} F f1; class X { F f; public: X(const F& f_) : f(f_){} X& operator=(const F& f_){f = f_; return *this;} }; int main(){ X x1(f0); // a:OK X x2 = f0; // b:NG(conversion from ‘void()’ to non-scalar type ‘X’ requested) X x3 = f1; // c:OK x1 = f0; // d:OK }
772 :はちみつ餃子 :2024/02/02(金) 00:09:46.55 ID:BQKaaqcl.net >>771 std::function ではなくごく単純なクラスでもエラーを再現できる。 暗黙の変換は原則としては多段には起こらず、 X→Y, Y→Z な変換が可能なときでも X→Z な変換はしない。 (プリミティブな型変換とクラスの型変換が連鎖することはある。) 以下の例だと X x1(1); という宣言のときに必要な「暗黙の変換」は int から foo という一段のものだけど X x2 = 2; としたときに必要なのは int から X だから一段の変換ではできない。 struct foo { foo(int x) {} foo(const foo&) = default; foo(void) = default; }; foo f1; class X { foo f; public: X(const X&) = default; X(const foo& f_) : f(f_) {} X& operator=(const foo f_) { f = f_; return *this; } }; int main() { X x1(1); // a:OK X x2 = 2; // b:NG(conversion from 'int' to non-scalar type 'X' requested) X x3 = f1; // c:OK x1 = 3; // d:OK }
773 :デフォルトの名無しさん :2024/02/02(金) 11:28:24.45 ID:xohFoxUO.net >>772 横からだけども > X x2 = 2; // b:NG(conversion from 'int' to non-scalar type 'X' requested) って X x2(2); と同義じゃねーの?
774 :はちみつ餃子 :2024/02/02(金) 12:19:41.13 ID:BQKaaqcl.net >>773 違うよ。 C++ では引数ひとつのコンストラクタは変換コンストラクタとして「も」使うことになっているから 違う文脈でも結果的に同じコンストラクタが呼び出されることになるけど 構文糖というわけではなくて違う解釈を経ている。
775 :デフォルトの名無しさん :2024/02/02(金) 12:28:48.56 ID:xohFoxUO.net 細かいなぁ
776 :はちみつ餃子 :2024/02/02(金) 18:32:30.30 ID:ZFQgO+dm.net 動くなら同義と考えても大した問題じゃないが、 ここでは実際に結果が違う (一方はエラーになる) ことの説明だから……
777 :デフォルトの名無しさん :2024/02/02(金) 22:30:30.14 ID:d8Flt8Cn.net これはなぜエラーになるのですか。 std::string s = "abc"; char name[10] = s.c_str(); error: array must be initialized with a brace-enclosed initializer 次と同等とみなせないのはなぜ? char name[10] = "abc";
778 :774 :2024/02/03(土) 05:00:19.85 ID:vGyzbOvf.net >>772 774だけどありがとう。暗黙だと変換が途中で途切れるかもなのか。 一番通って欲しいのがbなんだけど難しいっすね…
779 :デフォルトの名無しさん :2024/02/03(土) 05:21:33.46 ID:4Ieoi/Xm.net >>777 c_str()が返すのはchar* char name[10] = "abc"; は特別扱いで char name[10] = {'a', 'b', 'c', 0}; と同じ cの時からある雀の涙猫の額ばかりの文字列サポート
780 :はちみつ餃子 ◆8X2XSCHEME :2024/02/03(土) 08:35:44.53 ID:Sz70frqK.net >>778 少し表現を変えて良ければ >>771 の X x2 = f0; を X x2 = {f0}; と書くことでも通すことは出来るよ。 更に真面目に対処するならこんな感じかな。 https://wandbox.org/permlink/giXZnCETo64IkEez
781 :デフォルトの名無しさん :2024/02/03(土) 22:40:06.88 ID:mzdZy5dk.net >>779 あーそういうことですね。ありがとう。
782 :774 :2024/02/04(日) 02:54:38.53 ID:1VXaeA8L.net >>780 上は={}で通るのは確認してました。{}付けるとX型に見なされてコピーコンストラクタで初期化されるで合ってますか? 下の方、typenameの所は余りよく分からなかったですが強制的に引数の型で包んで(オブジェクト生成?)、コンストラクタの引数代入時に変換追加するということでいいですか? typename以下はdecltype(f_)((f_))でも良いんかなと思って変更してみたら通りました
783 :はちみつ餃子 :2024/02/04(日) 09:54:01.38 ID:/H29LerN.net >>782 > {}付けるとX型に見なされてコピーコンストラクタで初期化されるで合ってますか? いいえ。 直接初期化に該当します。 コピー (コピーコンストラクタの起動) は発生しません。 つまり X x1(f0); と書いた場合と同じということです。 ですから暗黙の変換を一段階すれば充分なのでエラーなく通ります。 > コンストラクタの引数代入時に変換追加するということでいいですか? いいえ。 何もしません。 コンパイルを通すためには不要ですので、 X のコンストラクタは template <class T> X(const T& f_) : f(f_) {} という定義だけでも問題なく動作します。 ただ、こうすると T は「あらゆる型」になりえます。 std::function<void()> に変換不可能な型も受け入れてしまうということです。 変換不可能であればいずれにしても最終的にはエラーなのですが、 X がデタラメな型も受け入れてから F に変換失敗してエラーになるよりは 特定の条件を満たす型以外を X が拒否するほうが一般的には都合がよいので そうなるようにしたのです。 コンパイルを通すために必要なのではなく通さないための処置です。
784 :774 :2024/02/04(日) 22:33:14.16 ID:1VXaeA8L.net >>783 上:初期化周りは似たような物が色々あって知識が曖昧でした。 下:あの記述は型制限の為ですか。読んでも意図がよく分からなかったので助かります。 説明ありがとうございました
785 :デフォルトの名無しさん :2024/02/10(土) 13:14:08.12 ID:KJGevrBa.net 質問なのですがstd::coutに対する (a) 固定小数点表示 (b) 小数以下精度指定(例えば20桁 (c) setw()される表示幅に対し足りない上位桁0埋め という表示仕様への変更と復旧は、変更が auto sv_flags = cout.flags(); cout << std::fixed; // (1) auto sv_prec = cout.precision(std::streamsize(20)); // (2) auto sv_fill = cout.fill(); cout << std::setfill('0'); // (3) 復旧が cout.flags(sv_flags); // (1)の変更から復旧 cout.precision(sv_prec); // (2)の変更から復旧 cout << setfill(sv_fill); // (3)の変更から復旧 と書くのが普通?シグネチャが不統一な印象があるますがもっとズバっとやる方法は無いもの? ((1)は変更にcoutのメソッドとマニピュレータが両方要り、復旧はcoutのメソッド。 (2)は変更も復旧もcoutのメソッドで済む。(3)は変更が(1)と同じパティーンで復旧がマニピュレータ……
786 :はちみつ餃子 :2024/02/10(土) 14:30:14.27 ID:XEL9SE6k.net >>785 ・ 直接的に入出力を司るのはバッファと呼ばれるオブジェクト (たとえば basic_streambuf など) ・ ストリームには対応するバッファがセットされている (あまりバッファを直接には操作しない) ・ 書式はストリームの状態として保持されている つまり同じバッファ (出力先) に対して異なるストリームをかぶせることが出来る。 一時的にだけ書式を変更するのであれば一時的なストリームを作るという方法がとれる。 コードで例を出すならこんな感じ。 #include <iostream> int main() { std::cout << 0.1 << std::endl; { std::ostream temp(std::cout.rdbuf()); temp.precision(30); temp << 0.2 << std::endl; temp << 0.3 << std::endl; } std::cout << 0.4 << std::endl; } 書式をストリームの状態として持つのがすこぶる不格好だというのは C++er にとっての共通認識になっていてようやく C++23 から std::print が導入されたので モダンな C++ を使えるならそっちを使ったほうが良い。 std::format なら C++20 から。
787 :デフォルトの名無しさん :2024/02/10(土) 15:00:10.91 ID:KJGevrBa.net >>786 ㌧クスなるほど…… 変更した書式の戻し忘れが無く、問題らしい問題点はほぼ無しで良さげ…… (しいて言えばstreamの中の作りを理解していなければtempが何の目的でそうするのかわかりにくい(コメント必須)なだけ、 std::printは手元のVC++がまだC++20対応止まりなので当面見送らざるおえない std::formatは…… 書式文字列が定数式限定という仕様のはいかがなものか…… 今回の用途では困りませんし、コンパイル時に書式の妥当性をチェックしてくれるのは良いのですだが、 仮に、C言語における自作printf()様インターフェースの関数(書式文字列と可変長引数を変数で受け取り、内部でvprintf()を呼ぶ) みたいなものを作りたくなった場合どうするんじゃとそこはかとなく疑問が……
788 :はちみつ餃子 :2024/02/10(土) 15:16:22.24 ID:XEL9SE6k.net >>787 実行時バージョンとして std::vformat も用意されている。
789 :デフォルトの名無しさん :2024/02/10(土) 15:25:38.54 ID:KJGevrBa.net >>788 なるほどなるほど、自作std::format()様関数は問題無く作成でき、 書式文字列が定数式限定が困るというのは杞憂ですたねサーセン;;; (実行時にならないと書式文字列が決まらない場合、コンパイル時チェックが原理的に不可能になるのはC言語のprintf()/vprintf()の関係も同じなのでC言語からの後退ではない
790 :はちみつ餃子 :2024/02/10(土) 16:29:24.58 ID:XEL9SE6k.net メンバとして copyfmt があって、これで書式を他のストリームにコピーすることも出来る。 書式を待避しておくだけのストリームを作ってそれにコピーしておいて 後で元に戻すという使い方をしてもいいんだけど、 どうせストリームをあらたに作るならそれを一時的なストリームとして使ったほうが自然かと思う。
791 :デフォルトの名無しさん :2024/02/11(日) 22:38:22.35 ID:smEWrSvv.net std::setのinsertで std::set<int> c1 = {1,2,3}; std::set<int> c2; c2.insert(c1); と書けると便利に思えますが解説のページを見るとできないようです。 なぜですか。
792 :デフォルトの名無しさん :2024/02/11(日) 22:45:16.04 ID:KNbj1ANO.net >>791 c2.insert(c1.begin (), c1.end ());
793 :はちみつ餃子 ◆8X2XSCHEME :2024/02/12(月) 11:50:11.55 ID:4VueJhli.net >>791 set に set を insert できる「だけ」ってのはあまり便利ではない。 集合というものをより汎用的に扱える枠組みとして C++20 から range という概念が導入された。 その枠組みを上手いこと成立させる言語機能 concept が長いこと検討されてて、 入る入ると言いながら C++20 までずれ込んでしまったという事情がある。 そんなわけで、 C++23 からなら insert_range が使えて、 これは range の条件を満たすものならなんでも受け入れられることになってる。
794 :デフォルトの名無しさん :2024/02/12(月) 21:37:56.53 ID:WngRm50l.net >>791 c2.merge(c1) ※C++17以降
795 :デフォルトの名無しさん :2024/02/13(火) 22:11:49.56 ID:TA8E1xmn.net みなさんありがとう。環境適合を優先して>>792 を使うことにします。
796 :デフォルトの名無しさん :2024/02/18(日) 00:05:28.51 ID:AtsZxBPF.net コンストラクタの初期化子リストの中で、どこまで柔軟に記述できるのかなーと思ってGPT先生に聞いたら、constまたはconstexprを返す関数のみ書けるとのことでした。 コンストラクタ内部のように好きなように書けないとわかり、初期化子リストの価値が低く感じられました。 そんな制限を設けてまで初期化子リストを導入した意図は何でしょう。
797 :デフォルトの名無しさん :2024/02/18(日) 01:13:17.69 ID:UTNyRtZE.net ChatGPTなんかあてにするな、平気で間違ったこと言うんだから constやconstexpr以外を返す関数だって普通に呼べる 試しにChatGPTに「メンバ初期化子リストではconstかconstexprを返す関数しか呼べませんが、これはなぜですか?」ってあえて間違った前提条件で質問してみたら、間違ってることに対する指摘は一切なかったし、さもこっちの質問が正しいかのようなそれっぽい返答が返ってきたし --- 俺: C++において、コンストラクタのメンバ初期化子リスト内ではconstまたはconstexprを返す関数しか呼ぶことができません。これはなぜでしょうか? ChatGPT: C++において、コンストラクタのメンバ初期化子リスト内でconstまたはconstexprを返す関数しか呼ぶことができる理由は、初期化子リストがオブジェクトの初期化に使用され、実行時のコードが生成されないためです。メンバ初期化子リストはコンストラクタの一部であり、オブジェクトが生成される際に実行されます。このリスト内での関数呼び出しはコンパイル時に解決され、オブジェクトの初期化に関する情報は実行時に生成されません。 constまたはconstexprを返さない関数をメンバ初期化子リスト内で呼ぶと、実行時にコードが生成される可能性があります。しかし、これはオブジェクトが生成される前に行われる初期化の一環であり、実行時の処理としては不要なオーバーヘッドを引き起こす可能性があります。 コンストラクタのメンバ初期化子リストは、メンバ変数を適切に初期化するためのものであり、できるだけ効率的に行われるように設計されています。そのため、コンパイル時に解決されるconstまたはconstexprを返す関数の呼び出しに限定されています。 --- だからAIをあてにしちゃダメだよ
798 :デフォルトの名無しさん :2024/02/19(月) 00:17:49.94 ID:bJlSKdBs.net >>797 私が聞いたときも似たような内容が含まれていて、そうなんだねと納得してしまいました。 ではコンストラクタに書けることはすべて書けるのですね。 なおこの問いは、入門書籍にはそこまで書かれてなくて、検索でもかんたんに見つからなかったので聞きました。
799 :はちみつ餃子 :2024/02/19(月) 02:33:45.03 ID:j7eyydGe.net >>798 たぶん >>796 で言う「初期化子リスト」は「メンバ初期化子リスト」だよね? これらは全くの別物。 明らかに混同しやすい用語だから仕方がない部分はあるんだが、 誤った用語を元に調べたら誤った解説に当たりやすいかもしれない。 メンバ初期化子リストは直接初期化 (direct-initialization) であると規定されていて 具体的な挙動の説明は初期化の章に丸投げされている。 https://timsong-cpp.github.io/cppwp/n3337/class.base.init#7 つまりメンバ初期化子リストに特有の事情というものはない。 普通に初期化なんで、そこに違いがあるかもしれないという想像をする人がいてそういう人のために 違いが無いと断りを入れる必要があるとは入門書の著者は思わなかったんだろう。 有るものを有ると説明することはあるが無いものを無いと殊更に強調して説明はあまりしない。
800 :デフォルトの名無しさん :2024/02/19(月) 22:58:00.95 ID:bJlSKdBs.net >>799 そうですメンバ初期化子リストです。どうもありがとう。 なお書籍には、メンバ変数名(引数)やメンバ変数名(0)の例ばかりでした。
801 :デフォルトの名無しさん :2024/02/26(月) 09:17:00.78 ID:KZUiymUx.net すみません、コンストラクタの宣言/定義で A() {}; とした場合と A() = default; と 書いた場合は何が違うのでしょうか。挙動とか意味だとか... あるいはある種のタイプクラスの場合は違いが生じるので注意とか....??
802 :はちみつ餃子 :2024/02/26(月) 09:36:14.06 ID:pFLZLcAJ.net >>801 default を指定した場合はデフォルトのルールでコンストラクタを生成する。 生成可能な条件が満たされなかった場合でもそれ自体はエラーにはならずに デフォルトコンストラクタは削除済と見做されるというルール。 そのときはデフォルトコンストラクタを必要とする使い方をした時点でエラーになる。
803 :はちみつ餃子 :2024/02/26(月) 09:39:35.86 ID:pFLZLcAJ.net つまりこんなことをしてもエラーは出ないが struct foo { foo() = delete; // デフォルトコンストラクタを削除 }; struct bar : foo { bar() = default; // デフォルトコンストラクタのデフォルト生成 }; int main(void) { } ↓ こういうことをするとエラー struct foo { foo() = delete; // デフォルトコンストラクタを削除 }; struct bar : foo { bar(){} }; int main(void) { }
804 :デフォルトの名無しさん :2024/03/02(土) 19:28:56.45 ID:fBQwxymt.net >>803 遅レスすみません。要は、コンストラクタの特定のパターンの用法をされたくない ときに使う感じ? でそれに該当するとコンパイルエラーになるわけですよね? 自分が気になったのは、ランタイム時に何かありうるかということです あるコードで、コンストラクタがdefault指定されているクラスが、別のクラス内 (親子関係にはない)でunique_ptrとして生成されたときに問題が生じたような 感じで.... ってもっと自分で調べてからレスしろって話ですが、現在そのコードに立ち戻る ことができず、とりあえず疑問だけを
805 :はちみつ餃子 ◆8X2XSCHEME :2024/03/02(土) 21:07:53.65 ID:JOojncXx.net C++ の仕様は場合分けで規則がごちゃごちゃしていることが多くて単純な一般原則として説明できない。 「要は」なんて一言でまとめられないよ。
806 :デフォルトの名無しさん :2024/03/03(日) 19:37:10.80 ID:HNPAS3Wj.net >>804 そういう目的ではないと見ていいよ >>803 が言ってるのは、基本的にはデフォルト実装でコンストラクタを作ってくれるが必ずではない、と言ってるだけ デフォルトの(引数無しの場合、何もしない。が、基底クラスの引数無しのコンストラクタはちゃんと呼んでくれる)コンストラクタでいい場合に使う。 A() {}と書くのと基本同じだよ
807 :デフォルトの名無しさん :2024/03/12(火) 20:26:30.54 ID:lzPsc8Dg.net 異なる型を含むような配列(的なもの)を作りたいのですが、可能でしょうか? 例えば template <T> struct NamedValue { string name; T value; } を定義して NamedValue<string>{a, b} や NamedValue<int>{c, d} などの型の異なる複数の値を、 一つの配列的なものに収納したいのです 例えばvectorは全要素が同じ型じゃないと駄目ですよね
808 :デフォルトの名無しさん :2024/03/12(火) 21:14:27.11 ID:irRbCjS4.net >>807 std::tuple
809 :デフォルトの名無しさん :2024/03/12(火) 21:19:48.50 ID:irRbCjS4.net あるいは要素数がコンパイル時に決まらないなら std::anyをコンテナに入れるとか?
810 :デフォルトの名無しさん :2024/03/12(火) 22:11:10.08 ID:lzPsc8Dg.net はい、要素数はコンパイル時に決まらないのでstd::anyのコンテナですかね で要素を取り出すときは、どの型なのかをチェックして挙動を...
811 :はちみつ餃子 :2024/03/12(火) 23:03:39.03 ID:WtXn1sYk.net もし >>807 の T の種類が限られているのなら std::variant を使ったほうが楽かもしれない。 std::visit を使えば型の種類ごとに処理を切り替えるのが便利なことがある。
812 :デフォルトの名無しさん :2024/03/23(土) 11:43:27.62 ID:YZ3MX9tD.net std::remove()ってファイルを消去する関数なんですね std::move()と名前が似ているのに全然違う
813 :デフォルトの名無しさん :2024/03/23(土) 12:38:58.15 ID:6dCwgWlj.net 名前空間か関数名にfileくらい入れとけって思うよね
814 :デフォルトの名無しさん :2024/03/23(土) 12:50:26.95 ID:epZulncV.net C言語以前にE言語の問題や さすがにそのくらいの英語の勉強はしておけと思う
815 :はちみつ餃子 :2024/03/23(土) 12:51:15.85 ID:szITgpvT.net C の規格から取り込んだものだから由来が違うんだよ。 今なら std::filesystem::remove があるからこちらを使うほうが良い作法だと思う。
816 :デフォルトの名無しさん :2024/03/23(土) 12:54:13.64 ID:aQWBK6SI.net >>812 >std::remove()ってファイルを消去する関数なんですね std::remove()ってSTLのstd::removeじゃなく? ちゃんとコンテナの要素をre-moveしてると思うが?
817 :デフォルトの名無しさん :2024/03/23(土) 13:38:01.48 ID:qgcdIGgP.net >>816 だよねえ?? >>812-815 が何を言ってるのか分からなくて怖い
818 :デフォルトの名無しさん :2024/03/23(土) 13:40:27.68 ID:qgcdIGgP.net ああ <cstdio>に int remove( const char* pathname ); ってのがあるのか https://en.cppreference.com/w/cpp/io/c/remove
819 :デフォルトの名無しさん :2024/03/24(日) 05:14:16.83 ID:DBUI72Gl.net >>815 なるほど。諸般の事情でC++14な環境で、ファイルを扱う関数を探していたら。 Boostに行く手もあるかもしれませんが、とりあえず。
820 :デフォルトの名無しさん :2024/03/24(日) 09:50:29.58 ID:FsPOi81N.net cstdio のは std:: 名前空間じゃないよね. ::remove だと思うけど
821 :はちみつ餃子 :2024/03/24(日) 12:13:25.60 ID:iaJ2USO3.net >>820 cstdio にある関数は std 名前空間にある。 ただしグローバル名前空間「にも」あって良い。 (無くても良い。) stdio.h の場合はグローバル名前空間で宣言されるが std 「にも」あってよい。 (無くても良い。)
822 :デフォルトの名無しさん :2024/04/14(日) 11:55:59.92 ID:Rac57Bvn.net ヒエッ……、、、ぎ、玉虫色……
823 :デフォルトの名無しさん :2024/04/20(土) 14:55:18.13 ID:nh5GJjX6.net 言語そのものではないのですが、コマンドラインのデバッガやIDEでSTLのコンテナの内容を 易しく表示してくれるのってありますか? 例えばvectorなら、単純に中の要素だけを列挙してくれたりとか ビルドにCMakeを使っているのでとりあえずCLionを使っていますが、これは 確かに変数の中身をリスト構造で見れますが、変数内の生のメンバー(M_なんちゃら等) 見えてる感じで、STLコンテナに関してはあまり親切ではないような デバッグの際は見えた方がいい場合もあるのでしょうが。なら表示が切り替えられたりとか? 自分はmacOSですが、他のプラットフォームにしかないものも参考に聞いてみたいです
824 :デフォルトの名無しさん :2024/04/26(金) 10:53:44.71 ID:kftlKAnq.net 今からC++を勉強するならC++20を基準にやっても構いませんか?
825 :デフォルトの名無しさん :2024/04/26(金) 10:59:40.04 ID:/+TxHGye.net c++20といわずc++23からやればいいのでは
826 :デフォルトの名無しさん :2024/04/26(金) 11:15:59.06 ID:kftlKAnq.net 最新の規格で勉強して必要に応じて古い知識をつけていくような学び方でいいの?
827 :デフォルトの名無しさん :2024/04/26(金) 12:03:42.74 ID:q/vvVdAs.net つべこべ言わずやれ 最短コースなんてない
828 :デフォルトの名無しさん :2024/04/26(金) 13:37:23.03 ID:+usxQk3U.net C++ は基礎の上に段階的に応用が乗っかっているような綺麗な構成ではない。 全部が入り組んで捏ねまわされてグダグダや。 そんでもってクソ巨大やねん。 どこから入っても同じ。
301 KB
新着レスの表示
掲示板に戻る
全部
前100
次100
最新50
read.cgi ver.24052200
本文 スレッドタイトル 投稿者