X



0からの、超初心者C++相談室
0001デフォルトの名無しさん
垢版 |
2018/11/12(月) 14:55:13.35ID:Tf74ZWQr
何にも知らない0からの出発、超初心者のためのC++相談室
0685デフォルトの名無しさん
垢版 |
2023/11/28(火) 00:37:23.98ID:dISnZSIc
2で通るはずだけどなぁ・・・ヘッダインクルードしてないとか?はさすがに無いか
あとC++17以降ならstatic constexprにすれば暗黙的にinline変数(定数)になるのでなお通るはず(宣言と同時に=ヘッダで定義できる)
0687デフォルトの名無しさん
垢版 |
2023/11/28(火) 06:02:30.27ID:fb4KLmhh
2、staticメンバにする方法。
.h
static const int TABLE[3]={1,2,3};
.cpp
extern const int TABLE[3];

もれはやらんけど
0688デフォルトの名無しさん
垢版 |
2023/11/28(火) 06:13:38.37ID:fb4KLmhh
あ、ごめん逆だった
.cpp
static const int TABLE[3]={1,2,3};
.h
extern const int TABLE[3];
0690はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/11/28(火) 10:25:57.66ID:mRTkdYl9
>>684
出来なかったというコードをそのまま提示して欲しい。
状況がよくわからないのに想像で対処法を考えてもしょうがない。
コードがちょっと長くなるなら
codetter とか wandbox とか ideone とかを使って。
0691デフォルトの名無しさん
垢版 |
2023/11/28(火) 10:27:57.27ID:vcMwjchf
クラス内の定数を外部に生出しとかしないから
enunとかで宣言はするけど
何番目が欲しいとかはサービス関数作るしなぁ
0692デフォルトの名無しさん
垢版 |
2023/11/28(火) 10:30:15.59ID:vcMwjchf
つか、static宣言の内部でしか使わないものを何でヘッダーファイルに書くの?
0693デフォルトの名無しさん
垢版 |
2023/11/28(火) 10:32:49.40ID:vcMwjchf
ヘッダーファイルはクラスコードの名刺みたいなもんで
外部にこう言う事が出来ますよってPRする為のファイルなんだから、普通は内部で完結してるものは書かないよ
0694デフォルトの名無しさん
垢版 |
2023/11/28(火) 10:35:09.02ID:vcMwjchf
マジックナンバー避ける為に#defineするとかも、cpp側の先頭に書くと、全ビルドしなくて済むしな
0695デフォルトの名無しさん
垢版 |
2023/11/28(火) 11:07:40.67ID:t7+ip2Xg
>>692
staticには複数の意味がある

>>683 の発想は h に static 描いてみたら「たまたま」エラーが消えたら ok みたいなやり方なんだろ
0696デフォルトの名無しさん
垢版 |
2023/11/28(火) 11:35:51.07ID:vcMwjchf
>>695
staticより「内部でしか使わない」って話の方を拾ってね
0698デフォルトの名無しさん
垢版 |
2023/11/28(火) 18:17:05.00ID:vcMwjchf
>>697
それならヘッダーファイルに書く必要無いやんけw
0699デフォルトの名無しさん
垢版 |
2023/11/28(火) 18:50:50.78ID:dISnZSIc
そら綺麗に一つのcppに全部そのクラスの実装を切り分けてるならcpp内にstaticでいいだろうけどね
0700デフォルトの名無しさん
垢版 |
2023/11/28(火) 20:09:09.84ID:vcMwjchf
そんな巨大なクラスは設計が間違ってないか?
0701デフォルトの名無しさん
垢版 |
2023/11/28(火) 20:12:44.23ID:bqHRuT95
>>680
> 「ダブルポインタ」ってのも可笑しな使われ方してることが数多く観測される

それなw
初心者ほどこの用語を使ってるように見える
初心者が集まるところでこれを流布してるやつがおるんやろな
ポインタへのポインタっていうスケーラブルな定義が理解できてなくて
アスタリスクいっこのポインタと、二個のぽいんたがある!って感じなんやろな
0702はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/11/28(火) 20:20:10.37ID:mRTkdYl9
>>700
この >>699 の言は逆のことを言ってると思う。
ひとつの翻訳単位にたくさんのクラス (の実装部分) を書くこともあるから
ファイルスコープにしたらスコープの範囲が広すぎる (制限にならん) やんけと言ってるように読める。
0703デフォルトの名無しさん
垢版 |
2023/11/28(火) 20:27:35.33ID:dISnZSIc
>>700
巨大とかじゃなくて、あんたの考えてるであろう1ヘッダに1ソースってのも指針としてはもちろん良いんだけど(そして質問者のケースに合ってるならいいけど)
例えばクラステンプレートになると、ソースに実装を書けないからヘッダのどこか(ヘッダからインクルードしてユーザーに見え辛い場所には出来るが)で実装を書くことになる
そうなるとその実装からソースファイル内のstaticな値など見えるわけがないだろ
0705デフォルトの名無しさん
垢版 |
2023/11/28(火) 20:57:18.00ID:dISnZSIc
まぁどれを選ぶかは本人の都合だけど、クラス定義の中にprivateで書くのが自然っちゃ自然な希ガス
0706デフォルトの名無しさん
垢版 |
2023/11/28(火) 21:00:29.03ID:HOP5xTTo
>例えばクラステンプレートになると、ソースに実装を書けないから

C++の設計ミスだな
特にテンプレ
0707デフォルトの名無しさん
垢版 |
2023/11/28(火) 21:55:43.79ID:vcMwjchf
テンプレートは単なる#defineだからなぁ
あんなもん#defineでの置き換えによる副作用を引き起こす悪習の最たるもんだよ
0708はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/11/28(火) 22:43:12.61ID:mRTkdYl9
一応はモジュールの概念の導入でちょっと良くなっているはずだが皆でこぞって移行するってほどには全然なってないからそこまで魅力的とは思われてないんやろね。
従来のスタイルと共存できるようにするのは C++ の立場では当然ではあるものの、悪い部分も捨てきれないことになりがち。
コンパイラのサポートもあまり熱心ではない(?)ような雰囲気だからそこも不安だし。
0709デフォルトの名無しさん
垢版 |
2023/11/28(火) 23:00:59.77ID:5UazaCro
どうも>>683です。
2のクラス名あり版でビルド通りました。

-sample.h
class sample_1 {
int a;
static const int TBL[3];
public:
sample_1();
};

-sample.cpp
#include "sample.h"
#include <iostream>

const int sample_1::TBL[3] = {1,2,3};

sample_1::sample_1() {
a = 2;
std::cout << TBL[a] << std::endl;
}

-main.cpp
#include <iostream>
#include "sample.h"

int main() {

sample_1 sa;
return 0;
}
0710デフォルトの名無しさん
垢版 |
2023/11/28(火) 23:06:12.31ID:5UazaCro
sample.hにTBL宣言なしで、

sample.cpp
#include "sample.h"
#include <iostream>

static const int TBL[3] = {1,2,3};

sample_1::sample_1() {
a = 2;
std::cout << TBL[a] << std::endl;
}

でもOKでした。こちらのstaticはC式の使い方ですね。

私はTBLが.hに現れない上の書き方がいいと思いますが、これを最適としてよさそうですか。
0712デフォルトの名無しさん
垢版 |
2023/11/29(水) 06:23:02.71ID:n75oaT1g
h に static 描くと単に相互干渉しないってだけで
インスタンスは造られまくって無駄リソース出まくるんじゃね
0713デフォルトの名無しさん
垢版 |
2023/11/29(水) 09:24:39.36ID:5+1qDy8t
奴は人の書き込み見ちゃいないよw
0714デフォルトの名無しさん
垢版 |
2023/11/30(木) 22:28:52.60ID:p6G1t8dm
sizeof(クラス名)を活用できる場面はありますか。
メンバによってはCのsizeof(構造体名)と同じ使い方ができると思いますが、
クラス一般について考えると思いつきません。

たとえば
std::string name;
がメンバ変数にあるともう、クラスのサイズは不定になりそうです。
あっ、new は・・・いや、mallocと違ってサイズ指定は不要ですね。
0715デフォルトの名無しさん
垢版 |
2023/11/30(木) 22:39:03.15ID:jq+Wc58z
>>714
>std::string name;
>がメンバ変数にあるともう、クラスのサイズは不定になりそうです。
確認してみましょう!
0716はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/11/30(木) 23:39:52.07ID:3QI4e6Tt
>>714
sizeof 演算子の適用結果は定数であることが保証される。
定数式として使うことができる。
std::string なども型の大きさが変動したりはしない。

C ではオペランドが VLA のときは sizeof の結果は定数にならないのだけれど C++ には VLA がないのでそういう例外はない。
(実際には処理系の拡張として VLA を使える場合もある。)

メモリアロケーションまわりを自分でコントロールする機会があれば普通のクラスの大きさを知る必要がある場合もなくはない。
それほど機会は多くないだろうけど。

本来 (?) の用途とは違うところで使われる場合もあって、
いわゆる SFINAE のトリックで sizeof が使われることもそれなりにある。
0718デフォルトの名無しさん
垢版 |
2023/12/01(金) 10:06:48.86ID:NZuUNSBe
おまえら、stdとboostどう使い分けてる?
0719デフォルトの名無しさん
垢版 |
2023/12/01(金) 13:58:15.55ID:aU4DjGEJ
>>717
stringも実際には確保したメモリのポインタと文字列サイズを持ってるだけ(だけではないけど簡単に言えば)なので
Cの構造体と大して変わらんのよ
0720デフォルトの名無しさん
垢版 |
2023/12/02(土) 07:29:47.55ID:qIqFVuKn
まず鍵を与え、文字列を暗号化等して暗号文文字列を返したい。

暗号化ユーティリティ風のクラスをつくり、鍵とstringを渡す案 (1)と、stringを継承して鍵保持メンバ関数と暗号化メンバ関数を追加する案(2)を思いつきました。

どちらがでも実現できるように思いますが、何か設計のポイントはありますかね。
暗号化等には既製ライブラリ使います。
0721はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/12/02(土) 09:03:43.92ID:w8ZlbPjQ
>>720
設計は総合的な判断だから単発の事情では判断しづらいというのは前置きとして書いておくけど、原則的には非メンバ関数として実装するほうがよい。
というよりも継承を使うほうが悪い。
「こういうメンバ関数があると便利」ということだけが理由なら継承を使うのは好ましくない。

プロジェクトの中で使う文字列を暗号化機能付きの文字列クラスで一貫して扱うならそれはそれでそんなに悪くないけど、通常は std::string 型のオブジェクトがあってそれを暗号化したいだけなのに別の型に変換にするという手間をかけるのがユーザーにとって便利だと思う?
0722はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/12/02(土) 11:45:21.73ID:w8ZlbPjQ
他の選択肢としてはストリームのアダプタにするとかいう方法も思いつく。
極端に大きなデータ (メモリに格納するには無理のある大きさ) にも対処したい場合は入出力と並行して処理することになるから、普通にストリームに書き出すのと同じように使ったら勝手に暗号化されてるというのは使う側としては楽でいい。
自分が使うものならそういう余計な抽象化層を挟むのは手間なだけかもしれないし、匙加減は微妙なところ。
0723デフォルトの名無しさん
垢版 |
2023/12/02(土) 12:16:48.61ID:0tC7Yjqi
sqliteとかの(暗号化もあるけど)暗号化しないバージョンのDBを使ってて
書き込むとき勝手に暗号化してくれると有難いな
0725デフォルトの名無しさん
垢版 |
2023/12/03(日) 06:49:36.39ID:xZHPSaOR
このスレはC++の話ではない書き込みが多すぎる
0727デフォルトの名無しさん
垢版 |
2023/12/03(日) 21:36:41.23ID:kkqQUehZ
>>721
ありがとう。
非メンバ関数として実装、と見て最初はなぜ?と思いましたが、確かに文字列変換だけでクラスオブジェクトはいらないですね。
string 暗号化(鍵, 平文);
だけあれば十分だと。
0728デフォルトの名無しさん
垢版 |
2023/12/04(月) 21:09:04.65ID:wzr7hFvb
msys2で開発環境を作りたくて
Windows10上にmsys2をインストールしてそのうえにpacmanからmingw-w64-x86_64-toolchainの最新版をインストールして
g++でコンパイルしてHello Worldを出力するところまではうまく行ったのですが
std::ifstream ifs("hoge.txt");
のような実行ファイルと同じ場所にある、あらかじめ用意したテキストファイルを読み込むだけのコードを書いてもファイルの読み込みに失敗します。
fstreamだけの問題ではなくfilesystemあたりをインクルードして適当な関数でテストしてもファイルが存在しないことになっていました。
どこで質問するのが適切なのかも見当がつかない状態なのですが原因に心当たりがある方がもしいらっしゃったら教えて頂けないでしょうか?
0732728
垢版 |
2023/12/12(火) 14:02:16.36ID:haJQSzRG
エラーは何もなくて変数に何も格納されてない状態だったので原因よくわかりませんでしたが
今回は>>731さんの言う通りになっていて解決できました
まだmsys2自体の仕様も十分に理解してなくて手が回っていない状態なのでこれでいったん失礼します
ありがとうございました!
0735デフォルトの名無しさん
垢版 |
2023/12/13(水) 16:17:33.78ID:b3+IUHNQ
プログラムの実行に必要な設定ファイルやデータファイルはカレントディレクトリではなく実行ファイルのパスを基準に決めたほうがいいね
0736はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/12/13(水) 17:12:54.61ID:vPv7AHCs
設定ファイルの類いは AppData フォルダに置くのがこのましいということになってる。
アプリケーションインストール用のフォルダ Program Files は書き込み権限が制限されているからそこに設定ファイルは置けない。
逆にどうしてもアプリケーションと設定ファイルを同じフォルダに置きたいなら Program Files にはインストールできない。
Msys2 内で使うソフトならホームディレクトリ (windows のホームディレクトリではなく msys2 が設定するホームディレクトリ、環境変数 HOME で取得できる) に設定ファイルを置くのが基本的な習慣。
0737デフォルトの名無しさん
垢版 |
2023/12/13(水) 17:14:51.41ID:Xh1qTD5r
起動時の引数や 自分のフルパスを取得するAPI経由で
実行ファイルのある場所を基点にどうこうすることが多いわ (Windows

unix だと usr と bin で分ける文化があるからそういうのはどうなってるんやろか
起動時のカレントのまま?
0738デフォルトの名無しさん
垢版 |
2023/12/13(水) 17:20:10.83ID:b3+IUHNQ
>>736
それはインストーラー使うアプリでしょ?
XCOPYインストールアプリの話だよ
0739デフォルトの名無しさん
垢版 |
2023/12/13(水) 17:23:03.86ID:HyXW4bJ5
カレントじゃ無くて、アプリが実行されたディレクトリに一緒に置いとくもんだろ?
ユーザー毎に違う設定にしたいなら、各ユーザーのホームディレクトリだろ?
0740はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/12/13(水) 18:03:20.75ID:vPv7AHCs
>>739
基本的にはそうだけどパッケージマネージャの管理方式との相性があったりする。
scoop で管理するなら設定ファイルも含めてひとつのフォルダに入れるほうが都合が良いと思う。
Msys2 内で pacman で管理するなら unix 風の流儀のほうが自然だし。
0741デフォルトの名無しさん
垢版 |
2023/12/13(水) 23:12:49.25ID:zjCiNOvz
グローバル位置に宣言したオブジェクトはmain前にコンストラクタが実行されますね。
仕様ではmain前に実行ということのほかに何か規定はありますか。

ある処理系で、main先頭である処理を呼び出すと成功するが、その処理を上記のコンストラクタから呼び出すと失敗するということがありました。
0742はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/12/14(木) 00:23:02.09ID:GWgG2Hfk
>>741
ややこしい規則が色々あってここには書ききれないがおおざっぱにはこんな感じかな。

・ 定数初期化が終わってから動的初期化がされる
・ 動的初期化でも条件が揃ったときは静的初期化扱いで早めに初期化する最適化をしてもよい (しなくてもよい)
・ 翻訳単位内の初期化順序は定義が現れた順序
・ 翻訳単位をまたぐとどちらが先に初期化されるかは規定されていない

特に翻訳単位を跨いだら決まってないってのは引っかかりがちなポイントで、
強い依存関係のあるものはあまり細かく分割しないほうがやりやすいと思う。
0743デフォルトの名無しさん
垢版 |
2023/12/14(木) 01:04:36.74ID:X6Ol8Z5z
普通は、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",
0745デフォルトの名無しさん
垢版 |
2024/01/01(月) 01:29:30.25ID:/rCM9JK/
このスレッドはゼロからC++と言っているが、C言語を知っている前提になっているよなw
0746デフォルトの名無しさん
垢版 |
2024/01/02(火) 11:00:49.80ID:TDOOgc4U
ワシも割と長く底辺コピペプログラマだけどなんでそんな詳しくなれるの?ってなる
有能と俺みたいな無能はどこでプログラマの生き方をたがえたのか
0747デフォルトの名無しさん
垢版 |
2024/01/02(火) 20:21:16.21ID:G9bvfkvl
>>746
頭の出来で決まっているからね

義務教育レベルで脱落した人間、日本語能力に問題がある人間は、プログラマーとしても問題がある。
0748はちみつ餃子 ◆8X2XSCHEME
垢版 |
2024/01/02(火) 21:40:20.68ID:RkRzwbey
知識は入れないと増えないというすごく当たり前の話。
長く放置してたら勝手に増えるなんてことはないよ。
0749デフォルトの名無しさん
垢版 |
2024/01/03(水) 08:18:02.54ID:3n4RUKo6
ガキの頃からマイコンBASICマガジン見てたけど
PCなかったしポケコンはあったからたまにあるポケコンゲームのソースをポチポチ入力してたけどそれで何かの知識になったか言われたら何にもならんかったな
0750デフォルトの名無しさん
垢版 |
2024/01/03(水) 08:26:31.48ID:uKn1SmuA
糞コテが
0751デフォルトの名無しさん
垢版 |
2024/01/03(水) 13:07:46.32ID:3mJitcl/
>>749
SHARPのポケコンでマシン語使ってシューティングゲーム作ったけど?
0752デフォルトの名無しさん
垢版 |
2024/01/03(水) 13:17:11.92ID:SgwYv7hO
ポケコン触ってたころが一番楽しかったです
手の中に物理キーボードと実行環境があるんだもん
一生遊べるよ
0754デフォルトの名無しさん
垢版 |
2024/01/10(水) 03:00:04.91ID:lNNg6PiH
Class Hogeの中でたくさんのFugaを管理するために
std::vector<std::unique_ptr<Fuga>>というメンバ変数を作りました
可変長引数テンプレートで複数のstd::unique_ptr<Fuga>を受け取るコンストラクタを書こうとしたのですが
std::unique_ptrがコピー禁止のためうまくいきませんでした。
Hoge(Args&&... args)
という形で右辺値参照を受け取ってうまいことムーブしてClass Hogeを初期化する方法ってありますか?
0755はちみつ餃子 ◆8X2XSCHEME
垢版 |
2024/01/10(水) 04:36:30.64ID:BOjhYgCx
>>754
できると思うけど、何をやりたくて何が上手くいかなかったのかイマイチわからない。
出来なかったコードをみせて。
0756デフォルトの名無しさん
垢版 |
2024/01/10(水) 11:27:22.10ID:lNNg6PiH
>>755
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がコピー禁止でエラーになったのでムーブにしたいけど書き方がわかりませんでした。
0757はちみつ餃子 ◆8X2XSCHEME
垢版 |
2024/01/10(水) 12:45:18.04ID:BOjhYgCx
>>756
この場合は 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));
}
0761デフォルトの名無しさん
垢版 |
2024/01/20(土) 18:17:15.80ID:9qysS+ur
時間のかかる処理があり、それが現在のスレッドをブロックして欲しくないので
その処理の部分に関してstd::async()の利用を検討していますが、
これって戻り値(future 型)でモニターしないといけない感じですか?
上記の処理はいつ終わるかは気にしないので別スレッドに投げっぱなし?で構わない
のですが... pthread_detach()的な?
0762はちみつ餃子 ◆8X2XSCHEME
垢版 |
2024/01/21(日) 12:43:25.73ID:4rk7TZPC
>>761
std::thread のメンバ関数に detach はあるけど、期待するのはこういうこと?

ただ、メインスレッドが終了すれば他のスレッドが稼働中でもプロセス終了処理に入るし、
プロセス終了処理の中で標準ライブラリの後始末している最中に他のスレッドが
標準ライブラリを使うようなことがあると破綻するかもしれない。

強引に終わらせて良いなら std::quick_exit で即死させるという方法も取れるが、
基本的にはプログラムを終わらせるときには全てのスレッドを終了させて (終了を待って) おくのが
普通だと思う。
0763デフォルトの名無しさん
垢版 |
2024/01/21(日) 21:48:26.38ID:zlvjOB5M
>>761ですが、お返事ありがとうございます。

はい、とりあえず thread::detach() を使うようにしました。1つの疑問は、
https://ja.cppreference.com/w/cpp/thread/future/~future によると
> ただし、その共有状態が std::async によって作成され、まだ準備完了になっておらず、これがその共有状態への最後の参照である場合は、ブロックする可能性があります。

ええ何それ、というのが発端でした(後出し失礼)。

確かに、メインスレッドの終了時のこともありますし、スレッドの後始末をちゃんと
した方が本当はいいように思われます。処理が長時間たっても終了しない場合
タイムアウトさせたりとかも。
何かシステマティックな方法等あるでしょうか。参考になるものがあれば...
0764はちみつ餃子 ◆8X2XSCHEME
垢版 |
2024/01/22(月) 12:54:36.50ID:T1sqP3ZB
>>763
メインスレッドの終了直前でまずは適当にフラグを立てた上で他のスレッドの終了まで待機する。
重い処理をしているスレッドの側で完了ではないにしても区切り良く終われるポイントでフラグを読んで
フラグが立っていれば後始末ルートに入ってスレッドを終了させる。
その結果としてメインスレッドの待機状態が終わってプロセスの終了。
というのが普通の大まかな流れだと思う。

その上で待機時間があまり長すぎるようだと強引にでも終わらせるとかの処理を入れるかも。

std::async は既存の関数を非同期化するちょっとしたユーティリティという立場なんじゃないかな。
それで事足りるときは便利で簡単だけど、細かい制御を勝手にやってくれるわけでもないし、
やろうとするとちょっとイマイチって感じ。
0765デフォルトの名無しさん
垢版 |
2024/01/28(日) 11:52:43.80ID:W0uCnQb3
質問なのですがどんな環境(ロケール設定)の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()が上書きしないように見えるのですがそういうもの?
0766はちみつ餃子 ◆8X2XSCHEME
垢版 |
2024/01/28(日) 13:12:39.75ID:hRRbWEE/
>>765
言語仕様通りならそれらの関数を呼び出さないようにすれば環境に固有の表現の変換はしない。

std::setlocale の設定が C の標準関数の挙動に影響するのはその通り。
ただし、様々な環境での「同じ動作」を期待するなら "C" を与えるべき。
空の文字列を渡した場合には環境に固有の設定であり、通常はシステムの設定が反映される。
プログラムは起動したときに setlocale(LC_ALL, "C"); 相当の状態なので、普通は書く必要もない。

std::locale::global での設定は C++ の標準ライブラリの挙動に影響するだけでなく std::setlocale での設定にも反映されるので両方を呼び出す必要はない。
これもプログラム起動時のロケール設定は "C" 相当になっているのでそれで良ければ呼び出す必要もない。
ただし、 std::locale::global に与える設定が名前を持たない場合 (つまり std::locale("") のような場合) は std::setlocale 相当の変更もするかどうかは規定されない。

imbue はストリームにロケールを結びつけるのでグローバル設定とは独立して機能する。
0767デフォルトの名無しさん
垢版 |
2024/01/28(日) 14:11:55.68ID:eBJAlicu
クラスオブジェクトの代入文に、=による単純コピーと、=演算子関数による独自コピーのどちらを使うか迷います。

たとえばメンバ変数が基本データ型の集まりなら単純コピーでいい。
今出くわしたのはメンバ変数がstd::array<int, 3>の場合で、まあたぶん単純コピーでよさそう?じゃあstd::vector<myclass>なら?などと疑問が深まります。

あとコピーコンストラクタによる初期化も合わせて考える必要がありそう。
0768はちみつ餃子 ◆8X2XSCHEME
垢版 |
2024/01/28(日) 14:36:51.31ID:hRRbWEE/
>>767
単純コピーってのは何のこと?
デフォルトで生成される代入演算子の意味で言ってるのかな?
0769デフォルトの名無しさん
垢版 |
2024/01/28(日) 15:36:35.20ID:W0uCnQb3
>>766
レス㌧クス、
>ただし、様々な環境での「同じ動作」を期待するなら "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" で行こうと思いまつ
0771はちみつ餃子 ◆8X2XSCHEME
垢版 |
2024/01/28(日) 16:38:46.52ID:hRRbWEE/
>>769
Windows での話か……。
msvcrt だとどうにもならなくて ucrt でちょっとマシになってるみたいな話題をこないだ Teratail で見たぞ。
0772はちみつ餃子 ◆8X2XSCHEME
垢版 |
2024/01/28(日) 16:52:54.16ID:hRRbWEE/
>>770
デフォルトで生成される代入演算子は全てのサブオブジェクト (基底とデータメンバ) を
代入演算子でコピーするのと同じ挙動になることになってる。
基底やデータメンバが適切に代入演算子を定義されているのならデフォルト生成にまかせてよいことが多い。

注意を払う必要がある典型的なものは生ポインタで、
ポインタをコピーしても指してる先のオブジェクトはひとつだから
そのへんの扱いはデフォルト生成だとあかんことになる。

あとは外部のリソースと結びついているオブジェクトだと単純にコピーできないか、コピーさせないこともあるな。
分かりやすい例で言うなら std::thread なんかはスレッドを抽象化したものだけど
オブジェクトをコピーしたらスレッドもぽんぽん増えるなんてことになっても困るし
スレッドひとつに対応しているオブジェクトがいくつもあるようでも困るのでコピーできないようになってる。

それぞれに事情があるので明瞭な判断基準があるわけじゃないけど、
デフォルト生成の結果がほんまに自分の意図通りに動作するか考えてみて
あかんなら自分で書くしかない。
0773デフォルトの名無しさん
垢版 |
2024/01/28(日) 17:03:17.17ID:eBJAlicu
>>772
いつもありがとうございます。
たいていはデフォルトでよさそうですね。
std::vectorは可変長配列ってことなので、<int>であってもデフォルトでいいのかなと心配に…あこれはvectorのほうで独自=定義されてるなら問題ないわけですね。
0774デフォルトの名無しさん
垢版 |
2024/01/30(火) 20:47:22.29ID:RcbbllHt
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
}
0775はちみつ餃子 ◆8X2XSCHEME
垢版 |
2024/02/02(金) 00:09:46.55ID:BQKaaqcl
>>774
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
}
0776デフォルトの名無しさん
垢版 |
2024/02/02(金) 11:28:24.45ID:xohFoxUO
>>775
横からだけども
> X x2 = 2; // b:NG(conversion from 'int' to non-scalar type 'X' requested)
って
X x2(2);
と同義じゃねーの?
0777はちみつ餃子 ◆8X2XSCHEME
垢版 |
2024/02/02(金) 12:19:41.13ID:BQKaaqcl
>>776
違うよ。
C++ では引数ひとつのコンストラクタは変換コンストラクタとして「も」使うことになっているから
違う文脈でも結果的に同じコンストラクタが呼び出されることになるけど
構文糖というわけではなくて違う解釈を経ている。
0778デフォルトの名無しさん
垢版 |
2024/02/02(金) 12:28:48.56ID:xohFoxUO
細かいなぁ
0779はちみつ餃子 ◆8X2XSCHEME
垢版 |
2024/02/02(金) 18:32:30.30ID:ZFQgO+dm
動くなら同義と考えても大した問題じゃないが、
ここでは実際に結果が違う (一方はエラーになる) ことの説明だから……
0780デフォルトの名無しさん
垢版 |
2024/02/02(金) 22:30:30.14ID:d8Flt8Cn
これはなぜエラーになるのですか。
std::string s = "abc";
char name[10] = s.c_str();

error: array must be initialized with a brace-enclosed initializer


次と同等とみなせないのはなぜ?
char name[10] = "abc";
0781774
垢版 |
2024/02/03(土) 05:00:19.85ID:vGyzbOvf
>>775 774だけどありがとう。暗黙だと変換が途中で途切れるかもなのか。
一番通って欲しいのがbなんだけど難しいっすね…
0782デフォルトの名無しさん
垢版 |
2024/02/03(土) 05:21:33.46ID:4Ieoi/Xm
>>780
c_str()が返すのはchar*
char name[10] = "abc"; は特別扱いで char name[10] = {'a', 'b', 'c', 0}; と同じ
cの時からある雀の涙猫の額ばかりの文字列サポート
0785774
垢版 |
2024/02/04(日) 02:54:38.53ID:1VXaeA8L
>>783 上は={}で通るのは確認してました。{}付けるとX型に見なされてコピーコンストラクタで初期化されるで合ってますか?
下の方、typenameの所は余りよく分からなかったですが強制的に引数の型で包んで(オブジェクト生成?)、コンストラクタの引数代入時に変換追加するということでいいですか?
typename以下はdecltype(f_)((f_))でも良いんかなと思って変更してみたら通りました
レスを投稿する