C++相談室 part141

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
垢版 |
2019/02/22(金) 03:07:43.52ID:MgOIx7iK
次スレを立てる時は本文の1行目に以下を追加して下さい。
!extend:on:vvvvv:1000:512

C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。

前スレ
C++相談室 part137 (正しくはpart138)
http://mevius.5ch.net/test/read.cgi/tech/1535353320/
C++相談室 part139
https://mevius.5ch.net/test/read.cgi/tech/1538755188/
C++相談室 part140
https://mevius.5ch.net/test/read.cgi/tech/1547326582/

このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.103【環境依存OK】
https://mevius.5ch.net/test/read.cgi/tech/1530384293/

■長いソースを貼るときはここへ。■
 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
0179KAC
垢版 |
2019/03/05(火) 01:01:35.52ID:zhV7s4kG
人によってセーフの定義が違ってたりしない?
0180デフォルトの名無しさん
垢版 |
2019/03/05(火) 01:03:06.00ID:w8adCz4V
C++11以降はセーフになったらしい(キリ
ttps://cpprefjp.github.io/lang/cpp11/static_initialization_thread_safely.html
0181デフォルトの名無しさん
垢版 |
2019/03/05(火) 01:04:55.09ID:w8adCz4V
Double Checked Lockingはジャヴァのメモリモデルがうまく対応できてなくて騒ぎになったことがある技法
0182デフォルトの名無しさん
垢版 |
2019/03/05(火) 01:11:12.97ID:w8adCz4V
もし関数内static変数の初期化をDouble Checked Lockingを使わずにスレッドセーフにしようとしたら、
関数に入る度に毎回馬鹿正直にクリティカルセクションに入るために1000クロックぐらい捨てることになってしまうま
スピンロックか何かの黒魔術で若干緩和する実装も有り得るかもしれんが基本は

ジャヴァではなくてC++の処理系がdouble checked lockingする分には
処理系がサポートするネイティブなアーキテクチャのみ考えれば良いから
問題が生じることは無いはずでとりあえずはめでたいと思うが、
0183デフォルトの名無しさん
垢版 |
2019/03/05(火) 01:34:00.08ID:Lvsoqpfj
グローバルなスタティック変数のように実行前に初期化する仕様にいまさら変えられない事情でもあったか。
0185デフォルトの名無しさん
垢版 |
2019/03/05(火) 01:40:59.82ID:w8adCz4V
あと複数の翻訳単位間ではグローバル変数の初期化順序は保証されない(保証しようが無い)から
そういう混乱を避けるために関数内staticは関数に入ったとき初期化されてホスイ

個人的には使わないから知らんが
0186デフォルトの名無しさん
垢版 |
2019/03/05(火) 02:16:13.00ID:VDry4yCP
>>171
unique_ptr<int[]> u(new int[2]{6, 7});
0188デフォルトの名無しさん
垢版 |
2019/03/05(火) 03:25:14.57ID:VDry4yCP
なんだろう
この違和感
0189デフォルトの名無しさん
垢版 |
2019/03/05(火) 04:45:14.68ID:mm49B1QN
ライブラリを作るときは、hpp にはクラスの定義を、cpp には実装を書く、と理解しています。

クラスのメンバでない関数はどう扱うべきでしょうか。
hpp にプロトタイプ宣言を、cpp に中身を書く、というので合っていますか。
0190デフォルトの名無しさん
垢版 |
2019/03/05(火) 04:47:10.42ID:VDry4yCP
inlineは?
0191デフォルトの名無しさん
垢版 |
2019/03/05(火) 04:50:23.83ID:xaYVlIsQ
なぜヘッダはクラス限定だとおもったんだ?
それ以前にクラス以外では使用したことがないのか?
0193デフォルトの名無しさん
垢版 |
2019/03/05(火) 05:18:53.19ID:3HlR5qin
ヘッダに書くのはクラスだから関数だからとかじゃなくて、複数の翻訳単位(≒cpp)で共通で使うかどうかで決まる
1つのcppの中でしか使わず外に見せないクラスや関数はcppの中でいいよ
0194デフォルトの名無しさん
垢版 |
2019/03/05(火) 05:48:49.52ID:mm49B1QN
>>190
inline なので(苦笑


>>191
ハ?
回答の体をなしていない。
> hpp にプロトタイプ宣言を、cpp に中身を書く
というやり方は許容されるという意味か。


>>192
覚えました。それで?


>>193
であれば、今私は複数の cpp ファイルを持つ予定はないので、ヘッダファイルは全く不要ということになります。
0195デフォルトの名無しさん
垢版 |
2019/03/05(火) 05:55:22.28ID:3HlR5qin
ライブラリなんだろ?
自分はcpp1つでも、他の人のcppで使わせるためのクラスや関数があるはずだ
それをヘッダに書け
0196デフォルトの名無しさん
垢版 |
2019/03/05(火) 05:59:24.21ID:mm49B1QN
>>195
その際、「プロトタイプ宣言はヘッダで、中身は cpp ファイルに」というルールかマナーか慣習はありますか
0197デフォルトの名無しさん
垢版 |
2019/03/05(火) 06:13:55.29ID:Lvsoqpfj
>>196
特にないから適当に他人のマネしとけばいいと思う。
0198デフォルトの名無しさん
垢版 |
2019/03/05(火) 11:45:31.15ID:HwCl8Q1J
>>193
>1つのcppの中でしか使わず外に見せないクラスや関数はcppの中でいいよ

staticは付けた方が良いですか?(苦笑
0199はちみつ餃子 ◆8X2XSCHEME
垢版 |
2019/03/05(火) 12:27:38.14ID:mHzXPPXa
内部リンケージにするには static を付けるよりも
無名の namespace に入れる方が良いやり方
みたいな雰囲気があるんだけど、
インデントが深くなるのがなんか嫌なんだよね。

インデントは文法に影響しないわけだから、
付けないという選択肢もとれるけど、
それはそれでなんだかなぁって感じだし、
結局は static を付けちゃうんよ。

無名 (unnamed) namespace って使う?
0200デフォルトの名無しさん
垢版 |
2019/03/05(火) 12:35:48.55ID:zIeyIuEy
関数よりファンクタの方が速いという情報を見たのですが、メンバ関数を入れ子クラスでメンバファンクタ化すると高速化が期待できますか?
0201デフォルトの名無しさん
垢版 |
2019/03/05(火) 12:41:35.39ID:xaYVlIsQ
コンパイラ次第だろ
実験
0202デフォルトの名無しさん
垢版 |
2019/03/05(火) 12:50:59.28ID:zIeyIuEy
VC2017で試したのですがテスト用の関数が単純すぎるのかグローバルのインライン関数、クラスのメンバ関数、クラスのメンバファンクタで差異が見られませんでした・・・
0203デフォルトの名無しさん
垢版 |
2019/03/05(火) 12:51:22.93ID:fI+Bf2nm
どこに書いてもいいだろ
他人の書いたコードなんてどうせ誰も読まないし
読ませたいならドキュメントしっかりさせたほうがいい
0204デフォルトの名無しさん
垢版 |
2019/03/05(火) 15:12:40.70ID:pv9Sbimr
>>202
その「ファンクタの方が速い」ってのは、一般的に関数ポインタを介するのと比較して、だよ
理由はインライン展開できるからであって、その実験で差異が出ないのは当然
0205デフォルトの名無しさん
垢版 |
2019/03/05(火) 19:05:23.76ID:A2wr9SaM
ストアドよりインデックスのほうが速いよってスレなかったっけ。
0207デフォルトの名無しさん
垢版 |
2019/03/05(火) 21:56:22.01ID:+aoESyYJ
>>199
使う理由としてはメンバ関数を内部リンケージにしたらリンク速くなるかもという期待だけだな
実際速くなるか調べたことないけど

明示的にstaticとある方が読みやすいし、無名はデバッガで見たときクソ見辛くなるし

c++はこういうダメ仕様多過ぎてうんざりだわ
0208デフォルトの名無しさん
垢版 |
2019/03/05(火) 22:06:02.21ID:fIhIM0AX
腐ったビルド戦略のせいで無駄なオブジェクトコードの重複を生じるのはゼロオーバーヘッド原則に反しないのか?は疑問だな
極一部のマニアしか使わない機能付けてオナニーしてる暇があったら、いいかげん時代錯誤なビルド処理の抜本的な見直しをやってほしい
0209デフォルトの名無しさん
垢版 |
2019/03/05(火) 22:21:06.27ID:R3KidTI1
メンバ関数の数はクラスのオブジェクト生成コストにどれくらい影響しますか?
0212デフォルトの名無しさん
垢版 |
2019/03/05(火) 23:19:26.52ID:R3KidTI1
ありがとうございます
というのもメンバ変数がなく多数の関数をまとめただけのクラスがあるのですが、次のどれがいいのか悩んでいまして
(1) 全部static関数にする
(2) クラスをnamespaceにして全部グローバル関数にする
(3) 呼び出す場所で逐次インスタンスを作成する
(4) 呼び出し側クラスでこのクラスのポインタをメンバとして持ち、コンストラクタでインスタンスを受け取るまたは生成する
この場合のベストプラクティスはありますか?
0214デフォルトの名無しさん
垢版 |
2019/03/06(水) 00:17:08.38ID:URVwFrjm
特に何もないなら2

templateと組み合わせるなら1とか3は多用するけど4は無いな
0215212
垢版 |
2019/03/06(水) 00:21:02.86ID:pU9AS85W
ありがとうございます
(2)でやってみることにします
0216デフォルトの名無しさん
垢版 |
2019/03/06(水) 00:32:13.90ID:Uli2bEJM
1 は、どうして君はすべての関数を、static 関数にできると思ったの?
static関数と、関数のライブラリ・モジュール化は関係ない

3, 4 は、どうして君は、関数を使うのにインスタンスが必要なの?

インスタンスの関数は、他の言語ではメソッドと言って、
そのインスタンスのメンバ変数を使うものに対して、特別な名称を付けている。
つまり、各インスタンスで値が異なるもの

メソッドは、一般的な関数とは異なる。
メソッドや一般的な関数と、関数のモジュール化は関係ない

例えば、Ruby では、
Math.log2( 8 ) #=> 3.0

このようにインスタンスを作らなくても、呼べる関数をモジュール関数と言って、
各インスタンスから呼ぶ関数を、メソッドと言って区別している
0217212
垢版 |
2019/03/06(水) 00:42:25.73ID:pU9AS85W
そう言われるとそうですね
オブジェクト指向ではmain関数以外全部クラス/構造体で作成するものだという先入観がありました
0218デフォルトの名無しさん
垢版 |
2019/03/06(水) 01:06:06.33ID:Riy5qgFP
>>214
無理矢理4にしたいケースを考えると、同じインターフェースを持つ関数群A,Bを場合によって切り替えて使いたい場合に敢えてインスタンスのポインタとすることもあるかな。今回の質問者の場合には当てはまらないだろうけど。
0219デフォルトの名無しさん
垢版 |
2019/03/06(水) 01:10:14.42ID:MDLmYlCa
>>193
>1つのcppの中でしか使わず外に見せないクラスや関数はcppの中でいいよ
名前無しでも何でも良いが、その場合はクラスはnamespaceの中に入れないと危険が危なすぐる…

同じ名前空間に属する同じシグネチャのFoo::func()が異なる関数として複数のcppで定義された場合、
どっちが呼ばれるか定まらない処理系が実在する(VC++2010とか
多分ODR違反で未定義動作なんだと思う
0220デフォルトの名無しさん
垢版 |
2019/03/06(水) 01:13:13.20ID:paKD8ls/
曖昧さは、利点にも欠点にもなりうる。
namespaceのグローバル関数ではなくクラスのスタティック関数にすることで曖昧さがなくなりコンパイルエラーを避けられる場合がある。
0221デフォルトの名無しさん
垢版 |
2019/03/06(水) 01:14:08.29ID:MDLmYlCa
>>219訂正
CPPでクラスを定義する場合は無名namespaceに入れないと危険が危なすぐる、
無名namespaceは異なる翻訳単位間では別名として扱われるから安全

一方、名前付きnamespaceでは異なるCPPで偶然
同じ名前空間に属する同じシグネチャのFoo::func()が作られてしまう危険性を排除できない
0222デフォルトの名無しさん
垢版 |
2019/03/06(水) 01:21:31.24ID:MDLmYlCa
>>220
そのクラスに非staticなメソッドを設けたとたん、
>>219と同じ話でどのFoo::func()が呼ばれるかわからないという不正な動作をする危険性が生じる

驚くべきことに、VC++2010の場合リンカが何のエラーも警告も出さない
それでいてしっかり変な動作になる(a.cppで定義したFoo::func()を呼んだつもりがb.cppで定義された同じシグネチャの別のFoo:func()が呼ばれる
0223KAC
垢版 |
2019/03/06(水) 01:53:40.57ID:tePy6oFI
>>216
C/C++では、staticなどキーワードが全く違う複数の意味で使われるから注意な。
0224216
垢版 |
2019/03/06(水) 02:00:53.56ID:Uli2bEJM
Ruby では、関数名のバッティングを避けるため、2重に囲む。
module 内にclass か、class内にclassを作る

module Net
class HTTP end
class FTP end
end

# インスタンス
Net::HTTP.new
Net::FTP.new
0226216
垢版 |
2019/03/06(水) 02:12:57.91ID:Uli2bEJM
static みたいな複雑な概念を、初心者が理解するのは難しい

スコープを限定する意味と、生成・破壊のタイミングの違いと、
2つの異なる概念を使うから、難しい

C++ は、すべてのリソースの生成・破壊のタイミングを追っかけるだけでも、大変

ドワンゴ江添の本「C++11/14 コア言語」にも書いてあるけど、

呼ばれる関数を探索する方法に、Andrew Koenig が提案した、実引数依存の名前探索 (ADL)もある

実引数依存の名前探索とは、C++において関数呼出時に与えられた引数の型に依存して、
呼び出す関数を探索 (lookup)する仕組みのことである。
英語ではKoenig lookup、argument dependent lookup (ADL)、argument dependent name lookupなどと呼ばれる
0227デフォルトの名無しさん
垢版 |
2019/03/06(水) 02:46:55.34ID:Riy5qgFP
>>216
>>212の(1)はクラスのstaticメンバ関数のことを言っているのだか、>>216>>226を見てるとそれを理解していないように思える。
いつも書籍や他人の発言を引用して〜〜では、という書き方ばかりしているのを見かけるが、自分の中に落とし込んで理解できてないならわざわざ書き込まないでくれ。
0229デフォルトの名無しさん
垢版 |
2019/03/06(水) 06:59:23.47ID:3Q0pfzsC
質問(ネタ振り)に対して見当違いな返答は混乱の元ってのはその通りとして。
読者の立場では、話題が広がってくのは嫌いじゃない。

投稿者の意見として消化しきれてなくても、
参考資料として「誰それの書いたナントカって本では…」と
紹介してくれるのも有難いし。

その上で「あの著者/本は間違いが多い、例えば…」とか、
「記述が古い、新しい規格でもっと便利な機能が追加された」みたいな
追加情報(具体的なもの)が出てくればなお嬉しい。
0230デフォルトの名無しさん
垢版 |
2019/03/06(水) 09:56:40.41ID:mg6kC0Yg
>>205
SQLの話ですか(苦笑)
0231デフォルトの名無しさん
垢版 |
2019/03/06(水) 18:18:48.94ID:paKD8ls/
名前なし名前空間を名前あり名前空間の中に作ることができる。便利ちゃあ便利。

namespace hoge {
namespace {
int foobar = 1;
};
};
0232デフォルトの名無しさん
垢版 |
2019/03/06(水) 21:53:00.33ID:paKD8ls/
64bit環境で文字列ストリームクラスstd::ostringstreamのインスタンスのスタックサイズが、
gccで376バイト, VS2017で232バイトもあるんだがもっと小さくできるんじゃないの?
ちなみに、std::string はgccとVS2017どちらも32バイト。
どうよ?
0233はちみつ餃子 ◆8X2XSCHEME
垢版 |
2019/03/06(水) 22:13:52.26ID:7/fqDaVy
>>232
std::ostringstream は文字列の一種というよりも入出力の系統だし、
std::basic_ostream を抱えているのでそんなもんちゃう?
0237デフォルトの名無しさん
垢版 |
2019/03/07(木) 01:36:59.97ID:7rstSYcJ
ostream, ofstream, ostringstreamのスタックサイズはgccとVS2017でそれぞれ以下のようになる。
gcc: ostream=112, ofstream=264, ostringstream=232
VS2017: ostream=272, ofstream=512 ostringstream=376

どうよ?
0238237
垢版 |
2019/03/07(木) 01:39:26.14ID:7rstSYcJ
間違えた。gccとVS2017は逆です。
何が言いたいというと、組み込みで気軽に使えるC++を目指すならiostream周りを何とかしないとね、という話。
0239デフォルトの名無しさん
垢版 |
2019/03/07(木) 01:41:48.62ID:1uoKMGSD
組み込みで気軽に使えるC++を目指してないしどこまで削れるかはベンダーの努力次第
0240237
垢版 |
2019/03/07(木) 01:45:06.81ID:7rstSYcJ
Cがコンパイル言語であるにもかかわらずprintf()系の構文解析でJITコンパイルする野暮ったさを解決すべく導入されたはずのiostreamがまったく活かされていないね。
0241デフォルトの名無しさん
垢版 |
2019/03/07(木) 01:45:09.29ID:E2AqWV/D
その程度のスタック消費でヒーヒー言うような組み込み案件でiostream使わんだろ
0242237
垢版 |
2019/03/07(木) 01:49:48.32ID:7rstSYcJ
>>241
スタック消費でヒーハー言う組み込み案件に進出するのもC++のひとつの課題なのでは有馬温泉
0245デフォルトの名無しさん
垢版 |
2019/03/07(木) 03:10:47.55ID:V0jGdMU/
class C : public std::function<int(int)>{};

というクラスを定義して、

int f(int i){ return i + 1; }

void main()
{
C c = f;
int i = c(1);
}

みたいな使い方って出来ないのでしょうか?
functional のヘッダを読んでみましたがさっぱりでした
0246はちみつ餃子 ◆8X2XSCHEME
垢版 |
2019/03/07(木) 03:21:15.84ID:fFrTWbSf
>>245
やりたいのはこういうこと?

class C : public std::function<int(int)>{
using std::function<int(int)>::function;
};
0248デフォルトの名無しさん
垢版 |
2019/03/07(木) 03:42:38.23ID:V0jGdMU/
>>246
すいません、
知識不足でそのusingが何を意味しているのか分かりませんが、
std::function<int(int)> と、
class C : public std::function<int(int)>{} を、
外側から同じように使いたいという感じです。

現在は、
class C { std::function<int(int)> F; };
みたいになっており、

C c;
c.F = f;
int i = c.F(1);

と、こんな風に使われています。
std::function<int(int)> を継承させてしまい、.Fを消したい感じです。
0249はちみつ餃子 ◆8X2XSCHEME
垢版 |
2019/03/07(木) 04:00:06.05ID:fFrTWbSf
>>248
単純に

class C : public std::function<int(int)>{}

とした場合、当然だけどクラス C にデフォルトで定義されるコンストラクタは
C::C(void); と C::C(const C&); だから、型が int (*)(int) であるような値を受け取る余地はない。

using std::function<int(int)>::function;

を入れると基底クラス std::function<int(int)> のコンストラクタである
std::function<int(int)>::function; をあたかも C のコンストラクタみたいにできる。
そんだけ。
public 継承してれば std::function<int(int)> の他のメンバはそのまま C のメンバとして
見えるからおおよそ期待する挙動になると思う。
0250デフォルトの名無しさん
垢版 |
2019/03/07(木) 04:06:09.21ID:V0jGdMU/
>>249
なるほど、そういう意味だったのですね。
ちょっと試してみます。ありがとうございます。
0252デフォルトの名無しさん
垢版 |
2019/03/08(金) 01:15:31.98ID:jsJl1WSX
テンプレートで何とかなりませんかね。
0254237
垢版 |
2019/03/08(金) 06:55:44.25ID:orP5LHkV
>>244 が提示してくれた from_chars, to_chars をgccに導入するにはどうしたらいい?
WSLのubuntuを使ってるんだけど規定でfrom_chars, to_charsの定義されたヘッダーファイルが入ってないっぽい。
0256デフォルトの名無しさん
垢版 |
2019/03/09(土) 11:07:13.09ID:jx9iLAiD
C++テンプレートテクニック第三版っていつ出るんですかね?
0258デフォルトの名無しさん
垢版 |
2019/03/10(日) 17:07:48.90ID:yzd/Af8M
テンプレート引数がクラスでpush_back()メンバを持っているというようなことを検査することはできますかね?
0260デフォルトの名無しさん
垢版 |
2019/03/10(日) 17:15:14.74ID:yzd/Af8M
でてくしょんいでおむってどの本見ればわかりますかね?
0261デフォルトの名無しさん
垢版 |
2019/03/10(日) 17:16:33.87ID:yzd/Af8M
decltype使えばいいのかな。
0263デフォルトの名無しさん
垢版 |
2019/03/10(日) 17:21:49.62ID:yzd/Af8M
ありがとう。
ちょっと読んでみます。
0264デフォルトの名無しさん
垢版 |
2019/03/10(日) 22:01:07.26ID:yzd/Af8M
std::byteの使い方がよくわからない。
暗黙の何とかを避けるのに使うんだろか。
0266デフォルトの名無しさん
垢版 |
2019/03/10(日) 22:30:00.78ID:yzd/Af8M
ソケットやファイルの入出力に使うって事かな?
0267デフォルトの名無しさん
垢版 |
2019/03/10(日) 22:49:36.48ID:8hqMg5Px
1バイトサイズの整数のつもりでcharを使ったらstreamで困ることがあったりしたしね。
0268デフォルトの名無しさん
垢版 |
2019/03/10(日) 23:15:04.53ID:yzd/Af8M
enum class byte : unsigned char { };
ってなってる。
0273デフォルトの名無しさん
垢版 |
2019/03/10(日) 23:57:35.21ID:6gF9+EwK
でも過去にそれで何かあったんでしょ
使うかどうかは任意だしある分には困らない
0276デフォルトの名無しさん
垢版 |
2019/03/11(月) 05:30:01.20ID:pTTv+VC9
>>265
なんで
uchar8_t
uchar16_t
uchar32_t
にしないんだろな
■ このスレッドは過去ログ倉庫に格納されています