【初心者歓迎】C/C++室 Ver.102【環境依存OK】

■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん
垢版 |
2017/11/04(土) 16:33:35.07ID:NYxCuvMY
エスケープシーケンスやWin32APIなどの環境依存なものもOK
そのような質問は必ず環境を書きましょう
半角空白やタブでのインデントはスレに貼ると無くなります

コードを貼れる所
http://codepad.org/
https://ideone.com/

前スレ
【初心者歓迎】C/C++室 Ver.101【環境依存OK】
https://mevius.5ch.net/test/read.cgi/tech/1500329247/
2018/04/17(火) 19:35:04.61ID:wvS91pUR
>>628
scanf("%d",&n);
int array[n]; //読み込んだ値を要素数にするってこういう事?
2018/04/17(火) 20:21:29.36ID:AHw7lgSX
基本的な事なんだろうけど、vectorを範囲ベースのforループしたいのですができません。
auto v = vector<int>()だとfor (auto &i : v)でいけるのですが、
newした場合はどうすればいいのでしょうか?
autov = new vector<int>(); for (auto &i : v)だと
begin関数が見つかりませんといってコンパイルできません。
どうすればいいでしょうか?
2018/04/17(火) 20:24:11.47ID:AHw7lgSX
すみませんでした。普通に逆参照すればいいのか。
auto v = new vector<int>(); for (auto &i : *v)
2018/04/17(火) 20:46:42.62ID:hZ2W0cz8
>>629
ありがとうございました
2018/04/18(水) 11:35:26.22ID:uQo81sbZ
MFCのアプリで排他制御のルーチンを作っていて疑問に思ったことなのですが、
CやC++の仕組みのことなので、こちらで質問させていただきます。

複数のスレッドから呼ばれる関数の内部は、
CCriticalSectionを使って排他制御しています。

void Test()
{
  static CCriticalSection cs;
  cs.Lock();
  :
  cs.Unlock();
}

関数内のstatic変数は、その関数が初めて呼ばれたときに
実体が作成されると理解しているのですが、
1回目のTest()でCCriticalSectionのコンストラクタを実行している最中に
他のスレッドがTest()を呼んだ場合、このコンストラクタ自体は、
正しく排他制御されるのでしょうか?
コンストラクタが終わるまで、他のスレッドは待ってくれるのでしょうか?

それとも、CCriticalSectionの変数は、
関数の外に置かなくてはいけないものでしょうか?

MFCの内部でも、AFXPlaySystemSound()などで
同じようなことをやっているようなのですが。
2018/04/18(水) 11:57:34.76ID:iSn0xXbj
https://cpprefjp.github.io/lang/cpp11/static_initialization_thread_safely.html
http://d.hatena.ne.jp/yohhoy/touch/20120309/p1
2018/04/18(水) 12:00:55.78ID:EfAk4eu6
>>633
C++11 でローカルなスタティック変数の初期化はスレッドセーフであると定められた。
(C++03 にはこの規定はなく、実際その頃はmsvcもgccもスレッドセーフではなかった)
msvc では 2015 から。

c言語バージョンの指定のほか、専用のオプションによっても有効化、無効化できる
以下を参照

https://docs.microsoft.com/ja-jp/cpp/build/reference/zc-threadsafeinit-thread-safe-local-static-initialization

gcc / clang では -fno-threadsafe-statics オプション
2018/04/18(水) 12:06:23.94ID:H8UzlwrM
他の言語ではコンパイルエラーで悩むことはないのですが、コンパイルが通らなくてかれこれ2日。
エラーの行番号見ても、あってるよーな?よくわからない。
どうすりゃいいの。
2018/04/18(水) 12:26:53.25ID:MXcoXWvI
独り言ならチラシの裏にかけ
2018/04/18(水) 12:28:10.26ID:iSn0xXbj
>>636
ソースとエラー貼って
2018/04/18(水) 12:39:00.98ID:8LhMtFC1
>>638
NDAを結ばないと出せません
2018/04/18(水) 12:48:05.38ID:Odk+F4n0
>>636
コードすら貼らないオツムの足りなさじゃ諦めろ
641633
垢版 |
2018/04/18(水) 12:59:22.55ID:uQo81sbZ
>>634-635
ありがとうございます。
VSは2015よりも前なので、このやり方はダメってことですね。
関数の外に置くようにします。

MFCの内部ではやっちゃってますが。
2018/04/18(水) 13:03:03.18ID:H8UzlwrM
なんだよ。このクソ言語。やっとわかったわ。

ちょっとずつコンパイルしていかねぇとダメじゃん。このクソ言語。
エラーの内容はhファイルの方に"{"が期待されるところに"}"がありますなエラー。
ヘッダファイルと睨めっこしても、{}の数あってるし仕方なくcppファイルの方の実装の中身を全部コメントアウトしたら
コンパイル通った。で、cppファイルの方を数行ずつコメントアウト解除したらエラーわかったわ。
hファイルにエラーがあるとかミスリードしてんじゃねぇよ。
2018/04/18(水) 13:07:10.12ID:iSn0xXbj
エラーも貼れないなら、助けるのはムリ。

テレパシーは秘密保持違反になるから、このスレッドでは君を助けられないね。

つーか、仕事中にパソコンで5チャンネル閲覧記録は、大きな企業なら会社にチェックされているだろうね。
2018/04/18(水) 13:12:55.50ID:H8UzlwrM
そりゃ、ソースコード全部張れば分かるとは思うけど、
エラーの内容は
「hファイルの方に"{"が期待されるところに"}"がありますなエラー。」
みたいなエラーでて、この意味ぐらい自分で分かるし。

だから、このエラーの内容だけ張っても君たちが分かるとは思えなかったら張りませんでした。
お手数かけました片山さん。
2018/04/18(水) 13:22:59.72ID:iSn0xXbj
May the source be with you.
2018/04/18(水) 13:25:36.89ID:whM0Cl8U
プリプロセッサの結果を見れば判るだろうに
2018/04/18(水) 13:37:08.45ID:H8UzlwrM
そうでしたか。まだ、C++やりだして1週間未満なものでして、そういうノウハウというか関連知識が
ありませんでした。

まだ、Visual Studioの「エラー一覧」ウィンドウしかまだ見てないもので。とりあえず、初心者の自分は
頻繁に数行書いたらコンパイルすることにします。
2018/04/18(水) 13:45:55.17ID:MXcoXWvI
C++の文法のクソさには誰も異論はない。
2018/04/18(水) 13:59:47.30ID:+aOsPa5t
プリプロセッサによる不便さだから c++ の文法とは全く関係ないけどな
2018/04/18(水) 14:01:11.21ID:v7hqXOET
クソどころじゃない
2018/04/18(水) 15:30:25.37ID:EU/tZBmZ
>>642
今後のためにそのエラーになる最少構成でやってみ
2018/04/18(水) 20:25:53.95ID:hZhORVVR
ヘッダファイルがこんなふうにconst用と非const用の関数があるとして

class A {
B b;
B& get() { return b; }
const B& get() const { return b; }
}

このBがくっそ長くて書くのが面倒な場合、autoで代用するのはまずい習慣ですか?

auto& get() { return b; }
auto& get() const { return b; }
2018/04/18(水) 20:49:19.46ID:cGcFIcRA
型名が長すぎるときは、typedef。
2018/04/18(水) 20:52:50.32ID:5Rgz0HeV
>>653
型の別名を定義することについての是非は置くとして、 typedef はオワコン。
using を使うのがモダンな C++ やで。
2018/04/18(水) 21:22:43.95ID:hZhORVVR
typedefやusingはなるべく使いたくないんですよね
やはりヘッダーの返り型くらいはちゃんと記述すべきですかね
イタレータとか長くなりがちだけど・・・
2018/04/18(水) 21:26:54.29ID:cGcFIcRA
こうだな。動くかどうか知らんけど。
auto& get() { return b; }
const auto& get() const { return b; }
2018/04/18(水) 21:27:07.88ID:5Rgz0HeV
decltype(b) でもええんやで。
2018/04/19(木) 01:18:42.72ID:AYGORpen
悩んでる時間があったら素直に全て書け
と思う
659デフォルトの名無しさん
垢版 |
2018/04/24(火) 10:32:40.90ID:Z9G2Fq/H
柴田望洋訳のC++の本とロベールのC++の本以外にまともな日本語のC++の本ってありますか?
2018/04/24(火) 12:27:26.17ID:1D4v+3Mx
ロベール、独習(Herbert Schildt)、柴田望洋、林 晴比古

修験者になって、数年山籠もりしたいのなら(笑)、ドワンゴ江添の、
C++11/14 コア言語、江添 亮、2015
2018/04/24(火) 13:18:05.66ID:+bGv0z3c
「C++の設計と進化」は良いよ
662デフォルトの名無しさん
垢版 |
2018/04/24(火) 15:48:30.83ID:Z9G2Fq/H
>>660-661

ありがとうございます。

Herbert Schildtの本は、ロベールに比べると細かい話がないように思います。
柴田さんの中級という本も細かい話がないように思います。
663デフォルトの名無しさん
垢版 |
2018/04/24(火) 18:56:34.08ID:Z9G2Fq/H
vector について質問です。

コピーコンストラクタ、operator=
について一応勉強したのですが、 vector などのクラスでは、
コピーコンストラクタや operator= はどうなっているのでしょうか?
2018/04/24(火) 19:23:44.30ID:4uyKjeBM
実際にヘッダ読んで見るしかないと思うが
ディープコピーしてるよとしか
2018/04/24(火) 19:27:47.73ID:Eukzbh8y
Visual Studioなどでデバッグするとヘッダーが見れるよ。vectorはテンプレートのクラスだから、
読み進めるにはテンプレートの知識が必要かもね。
666デフォルトの名無しさん
垢版 |
2018/04/24(火) 19:32:21.39ID:Z9G2Fq/H
>>664

ありがとうございました。

ディープコピーでしたら、使う上では、何も考えずに関数の引数として渡したり、
関数から返したりしてもかまわないですね。

>>665

ありがとうございました。
2018/04/24(火) 19:40:11.28ID:4uyKjeBM
>>666
それはディープコピーのコストがかさむのでおすすめしない
2018/04/24(火) 20:11:58.65ID:Ukt80uX+
>>666
>何も考えず引数で渡しても良いですね

何をもってして「良い」と評価するのかはわかりませんが、
そういうのは拙い知識で独断せずそこら中にある
経験豊富な先人の書いたコードを読んで真似するのがいいですよ
引数は大抵 const 参照で渡しているでしょう
2018/04/26(木) 01:34:48.58ID:Z7x9U0tp
class TestA
{
TestA() {}
~TestA() {}
};
class TestB
{
TestB() {}
~TestB() {}
TestA getA() { return TestA(); }
};
int main() { TestB b; TestA a = b.getA(); }

TestBクラスの getA() メソッドがこのテストコードで正しく動作しているのですが、TestAの
インスタンスは一体どこで作られてるんでしょうか?
TestA getA() { TestA a; return a; }
としないでいきなり reurn TestA() で良い理由が良く分かりませんでした。
2018/04/26(木) 07:25:57.17ID:E0/AuDcr
>>669
どこのメモリにどう作られているのかという質問だと思うけど、
C や C++ では式の値として構造体やオブジェクトが認められていて、
コンパイラがどこぞにメモリを用意して上手いこと作ってくれることになっている。

式や式の一部の値としてだけ現れて変数に格納されないオブジェクトはテンポラリーオブジェクトとか言うので、
詳細はテンポラリーオブジェクトでぐぐって。

>>669
のmain はテンポラリーオブジェクトを使って b を用意せず TestB().getA(); ともかける


ところで今回の質問の、関数の戻り値に関するコンパイラの動作は
「戻り値最適化」なる最適化によって色々複雑なことになっているので
これは自分で戻り値最適化でググって調べて欲しい。
2018/04/26(木) 07:37:06.21ID:E0/AuDcr
>>669
質問が文法的なことについてだとすると、式中の項ととして
TestA()
std::string("foo")
などのように型名にコンストラタの引数を加えて関数呼び出しのように書くと
テンポラリーオブジェクトを生成してそれを値とする頃ということになる。


size_t l = std::string("abc").length();

std::string 型のテンポラリーオブジェクト(中身は"abc") が作られ、
それのメンバ関数 length が呼ばれ、l はその値(3)で初期化される。
2018/04/26(木) 11:26:25.34ID:Z7x9U0tp
>>670-671
詳細をありがとうございました。
大変良く解りました。より深くは自分でググってみます。
2018/04/26(木) 14:19:03.06ID:LZqqVlEY
共同ツール 1
https://seleck.cc/685

https://trello.com/
ボードのメニュー → Power-Upsから拡張可能 Slack DropBoxなど
Trello Chrome拡張機能 elegant
ttp://www.kikakulabo.com/service-eft/
trelloのオープンソースあり

共同ツール 2
https://www.google.com/intl/ja_jp/sheets/about/

共同ツール 3
https://slack.com/intl/ja-jp
https://www.dropbox.com/ja/
https://bitbucket.org/
https://ja.atlassian.com/software/sourcetree
https://sketchapp.com/extensions/plugins/
ttp://photoshopvip.net/103903

ttps://goodpatch.com/blog/sketch-plugins/
674デフォルトの名無しさん
垢版 |
2018/04/27(金) 13:24:43.31ID:wnXDwKhi
for (int i = 0; i < n + 1; ++i) {;}

とやると、 i が n + 1 未満かどうかの判定をする際、毎度
n + 1 を計算してそれを i と比較するということになるので
しょうか?

もし、そうなら、

m = n + 1
for (int i = 0; i < m; ++i) {;}

としたほうがよいのでしょうか?
2018/04/27(金) 13:35:12.84ID:GhhThAV7
>>674
ただの整数の足し算程度なら最適化されることが期待できるのであまり気にしなくていい。
676デフォルトの名無しさん
垢版 |
2018/04/27(金) 14:09:53.91ID:ouRrzssA
【マイトLーヤとPS4】 FFとDQの最新作、VR開発は危険、プレーヤーの日常感覚を損なうおそれ
http://rosie.5ch.net/test/read.cgi/liveplus/1524621704/l50
2018/04/27(金) 18:21:42.79ID:qED012zx
https://ideone.com/TVzVzF

上記のコードで、read関数を持ったIReadableクラス(基底クラス)があって、そのクラスから派生したCFileReaderクラス、
直接は派生していないけどread関数を持ったCMemoryReaderクラスがあって、その両方を受け取れるvector<IReadable*>を作りたいのですがコンパイルが通りません。
どうしたらいいでしょうか? どなたか教えてください。。。
2018/04/27(金) 18:38:42.04ID:yKF4ET93
>>674
いまだに最適化されないコンパイラもあることはある
8bitマイコンとかの話

あと、nがvolatileだと当然毎回計算する
nがSFRだったり複数スレッド共有変数だったりするなら気を付けよう

普通は気にしなくて大丈夫
コンパイラの最適化の基本の基本なので

このループの比較がパフォーマンスに大きく影響するなら
高速化テクニックは色々とある
2018/04/27(金) 19:03:28.59ID:uctWpHV6
>>677
なんとなく互換性のある read を持つものをエンベロープして IReadable になるエンベロープクラスを用いるのはどう?

ifstream も IReadable じゃないからエンベロープする。

https://ideone.com/27yhhu
2018/04/27(金) 19:06:52.81ID:O6TOHWbP
>>674
> for (int i = 0; i <= n; ++i) {;}
2018/04/27(金) 19:18:38.40ID:uctWpHV6
for ループといえばつい手癖で
for (int i =0; i < count-1; ++i ) {...}
と書いてて、
後日に count を int から size_t にしたとき
countが0のケースではまったことがあるなあ

for (int i =0; i + 1 < count; ++i ) {...}
と書けば良いだけなんだけど
2018/04/27(金) 19:27:34.55ID:mctUhDKo
n+1未満とn以下は違うと思うの
2018/04/27(金) 19:33:05.63ID:AimUsleE
>>681
それcountが1でも全くループしないというヘンテコ仕様だけど
そんなもの手癖で書くの?
2018/04/27(金) 19:37:07.17ID:uctWpHV6
>>683
隣り合った2項、例えばv[i] と v[i+1] を用いた処理をするとか
後続のものがある項だけ処理するとか良くある
685デフォルトの名無しさん
垢版 |
2018/04/27(金) 19:37:30.10ID:wnXDwKhi
int **a を利用して2次元の動的配列を作ります。
a を関数に渡して、計算に利用します。
2次元配列 a の要素は変更しないので、

int func(const int **a){ ... }

としました。

main 内には以下のように書きました。

ret = func(a);

すると、 a を int** から const int** に変換できませんというエラーが出てしまいます。

これはなぜでしょうか?
686デフォルトの名無しさん
垢版 |
2018/04/27(金) 19:39:48.54ID:wnXDwKhi
>>675
>>678
>>680

ありがとうございました。
2018/04/27(金) 19:49:10.59ID:O6TOHWbP
>>682
ん?
レアケースを語り出すのか?
2018/04/27(金) 19:51:18.26ID:mctUhDKo
>>683
そんなにヘンテコでもないと思う

for (size_t count = 0 ; count < 10 ; count++){
for (size_t i = 0 ; i < count - 1 ; i++){
....
}
}

こんなのはありがちかと
2018/04/27(金) 19:52:51.39ID:mctUhDKo
>>687
レアケースっていうか
nが小数の場合だな
2018/04/27(金) 20:02:30.96ID:AimUsleE
ふむ、なくはないか。
やはり条件の方に+1とか-1とか書くんじゃなくて初期値変える方が素直だろうな。
最適化の下手なコンパイラ対策も含めて。
2018/04/27(金) 20:03:21.75ID:O6TOHWbP
>>689
だからそう言うのをレアケースって言ってるんだが...
よく書くと言うなら多分住む世界が違う
2018/04/27(金) 20:10:35.47ID:HF3+Vuoy
レイアース
693デフォルトの名無しさん
垢版 |
2018/04/27(金) 20:28:24.05ID:wnXDwKhi
>>685

具体的なコードは以下です:

int func(const int **a) {
return 0;
}

int main() {
int n = 10;
int **a = new int*[n];
for (int i = 0; i < n; ++i) {
a[i] = new int[n];
}

func(a);

for (int i = 0; i < n; ++i) {
delete[] a[i];
}
delete[] a;
}
2018/04/27(金) 20:32:49.73ID:GhhThAV7
>>692
さくらの続編を放送してる今日この頃、レイアースの第三章もワンチャン有るかもな!
2018/04/27(金) 20:36:06.84ID:mctUhDKo
>>687
そんな事言ったら
countが0でループだってレアケースだぞ
2018/04/27(金) 20:43:41.07ID:mctUhDKo
>>693
const付きに変換出来るのは
ポインタの先がconstに変わる場合

int finc(int * const * a) なら大丈夫
2018/04/27(金) 20:52:32.49ID:wnXDwKhi
ありがとうございます。

const についてよくわからないのですが、

func の中で、

a[i][j] = 1;

みたいなことをできないようにしたいのですが、どうすればいいでしょうか?
2018/04/27(金) 20:55:03.35ID:qED012zx
>>679
ありがとうございます。その方法で取りあえずの目的は果たせそうなのですが、ほかの方法はないでしょうか?
というのも、他のクラスでラッピングしたりキャストしたりせずにifstreamを食わせたいのです。
たとえば、STLの各種関数はポインタでもvector等のコンテナでも大体OKですよね?
あれと同様に関数ポインタでもクラスのインスタンスへのポインタでもread()を持つものなら何でも突っ込めるようにしてforでぶん回したいのです。
標準のコンテナや自作クラス等の違いを吸収できるような構造にしたいのです。条件が後出しになってしまって申し訳ありません。
2018/04/27(金) 20:57:43.26ID:mctUhDKo
キャスト
が一番コストが少ないと思う

関数の中で
delete [] a[i];
a[i] = new int[10];
は出来ても良いの?
2018/04/27(金) 20:58:32.28ID:mctUhDKo
>>699>>697あて
2018/04/27(金) 21:19:24.66ID:wnXDwKhi
>>699

ありがとうございます。

ちょっと回答が理解できないため、質問を代えさせてください

以下のプログラムの func はNGなのに func2 はOKなのはなぜでしょうか?
2018/04/27(金) 21:19:40.66ID:wnXDwKhi
int func(const int **a) {
return 0;
}

int func2(const int *b) {
return 0;
}

int main() {
int n = 10;
int **a = new int*[n];
for (int i = 0; i < n; ++i) {
a[i] = new int[n];
}

func(a);

int *b = new int[n];

func2(b);

for (int i = 0; i < n; ++i) {
delete[] a[i];
}
delete[] a;

delete[] b;
}
2018/04/27(金) 21:47:52.98ID:uctWpHV6
>>701
それは c / c++ の欠点の1つで、
T * は const T * に文句も言わず変換してくれるが
T ** は const T ** に変換してくれないという問題
T は const T と定数性以外 compatible だよね、という判断を 1 段階しかしてくれない。

キャストが必要

const_cast<const int**>(a) など
2018/04/27(金) 22:48:56.90ID:bqnCmOTp
>>702
皆が言っているのは質問の内容とはちょっと違うけど、
func の中で a[0] = 0; などを禁止するために内側のポインタ自体も const にして

const int * const * にした方がいいよということ
705704
垢版 |
2018/04/27(金) 22:53:34.55ID:bqnCmOTp
いやごめん

func(int * const * )にすればコンパイル通るのか…
T * const * ==> const T * const * という変換は暗黙でokなのか
自分がバカでした
2018/04/29(日) 14:10:11.64ID:uFYPLUkV
>>703
欠点なの?
T ** を const T ** に勝手に変換されると困るんだが。
2018/04/29(日) 15:26:18.04ID:AQKaesvC
T * を const T * には勝手に変換するけどな
2018/04/29(日) 15:27:57.34ID:AQKaesvC
T * を volatile T * にも
2018/04/29(日) 16:08:44.48ID:p2Z/45DS
>>706
ちょっと興味があるので困るコードを教えて
2018/04/29(日) 16:11:13.28ID:p2Z/45DS
>>705
慌ててたのかこのレス書き間違ってた

func(const int * const * )にすればコンパイル通る、
T ** ==> const T * const * という変換は暗黙でok、
と書きたかった(全然違うな)
711デフォルトの名無しさん
垢版 |
2018/04/29(日) 18:37:23.21ID:uFYPLUkV
>>709
int** ipp;
const int ci=0;
const int ** cipp;
cipp = ipp;
*cipp= &ci;
**ipp = 3;
712711
垢版 |
2018/04/29(日) 18:50:17.15ID:uFYPLUkV
おっと ipp の初期化忘れた
int** ipp;
const int ci=0;
const int ** cipp;
int *ip;
ipp = &ip;
cipp = ipp;
*cipp= &ci;
**ipp = 3;
2018/04/29(日) 18:55:31.07ID:tn8JNm3m
ロベールの本に、

ios::out | ios::trunc

が意味がないと書いてあります。

既存のファイルを破棄してから書き込むということだとすると意味があるように思います。

ios::in | ios::out | ios::trunc とした場合のみ意味があると書いてあります。

どういう意味なのでしょうか?
2018/04/29(日) 23:14:14.46ID:hAJLRgtx
truncate は、ファイルサイズを切り詰め・縮小する。
これは、読み書き両用時に使える機能

ファイルを読み込んで、ファイルサイズを縮小して書き込む

ファイルの書き込みでは、使えない。
書き込みでは、ファイルサイズ0で開くから、前のファイルが消える
2018/04/30(月) 03:21:44.30ID:/NJkj9K4
>>712
なるほどね。
T ** => cont T ** は許すとcont T を操作できてしまうから禁止されていて、

T * => const T *
T ** => const T * const *
...(以下略)
にはその問題が無いから許可されているわけか
716デフォルトの名無しさん
垢版 |
2018/05/05(土) 10:57:39.35ID:dx2uIifv
file.read((char*)buf, sizeof buf);

は buf のサイズ分だけ読み込めということだと思います。
ファイルの最後の部分を読み込むとき、サイズが WIDTH 未満の場合にはどうなるのでしょうか?

fstream file;
file.open("hello.txt", ios::in | ios::binary);
do {
unsigned char buf[WIDTH];
file.read((char*)buf, sizeof buf);
for (int i = 0, size = file.gcount(); i < size; ++i) {
printf("%02X ", buf[i]);
}
cout << endl;
} while (!file.eof());

file.close(); 👀
Rock54: Caution(BBR-MD5:1341adc37120578f18dba9451e6c8c3b)
717デフォルトの名無しさん
垢版 |
2018/05/05(土) 11:15:19.94
>>716
https://cpprefjp.github.io/reference/istream/basic_istream/read.html
2018/05/05(土) 11:22:41.78ID:dx2uIifv
>>717

ありがとうございました。

あともう一つ質問させてください:

ロベールの本なのですが、

int n = 0x41424344;
file.write((const char*)&n, sizeof n);

というコードがあるページにあります。

その少し後ろのページには、以下のコードがあります。

char buf[BUF_SIZE];
dst.write(buf, src.gcount());

ここで、なぜ

dst.write((const char*)buf, src.gcount());

としていないのでしょうか?
719デフォルトの名無しさん
垢版 |
2018/05/05(土) 11:28:13.02ID:4WOSF73M
【マイトLーヤとUFO】 『月面にはウサギやウルフが棲息』   『宇宙人グレイは溶けてゼリーに』
http://rosie.5ch.net/test/read.cgi/liveplus/1525483483/l50
2018/05/05(土) 11:56:29.00ID:y1NIMmWz
>>718
char *はconst char *に互換だから。constは書き換えないという意味で、constなしはconstありに対して互換性がある。
721デフォルトの名無しさん
垢版 |
2018/05/05(土) 11:58:03.35ID:dx2uIifv
すみません。もう一つ質問です。
またロベールの本なんですが、以下のコードが書いてあります。
ファイルから入力中にエラーが起きたときの対処法です。

if(src.fail()) {

ではなく、

if(src.fail() && ! src.eof()) {

と書いてあります。その理由として、

「読み込みの場合はファイルの終端に到達した際も fail メンバ関数が
真となるため、 eof メンバ関数が真になる場合は除外しておきます。」

と書いてあります。

そこで質問です。

ファイルの終端の直前の部分を読み込む最後の読み込みの際に何等かのエラーが起こった場合、
src.fail() == true かつ src.eof() == true となります。
そのため、
src.fail() && ! src.eof() == false となってしまいます。

この場合、読み込みエラーが起こったにもかかわらず、その対処ができないことになりはしないでしょうか?

それともロベールさんのコードはOKなコードなんでしょうか?
722デフォルトの名無しさん
垢版 |
2018/05/05(土) 11:58:46.39ID:dx2uIifv
fstream src;



char buf[BUF_SIZE];
src.read(buf, sizeof buf);
if(src.fail() && ! src.eof()) {
error = true;
break;
}
2018/05/05(土) 12:03:26.22ID:dx2uIifv
>>720

ありがとうございます。

つまりどちらもエラーにはならないということですね。

ですが、記述が統一していない理由というのは何か考えられるでしょうか?

int n = 0x41424344;
file.write((const char*)&n, sizeof n);

に const がついているのは、 n は int 型だから write に渡すときには絶対に
キャストしなければならない。(char *) でもいいが、どうせなら const もつけて
しまおうということですかね?


一方、

char buf[BUF_SIZE];
dst.write(buf, src.gcount());

の方は、キャストの必要がないからわざわざ (const char*) とキャストすることも
ないかなという感じですかね?
2018/05/05(土) 12:05:14.84ID:dx2uIifv
ロベールさんの本は色々細かいことが書いてあって有用なのですが、なぜこういうコードなんだろう?という
疑問を持って読んでいくと次から次へと疑問が生まれてきて読み進むのが大変です。
725デフォルトの名無しさん
垢版 |
2018/05/05(土) 12:18:38.57
>>721
>>717 再読のこと
2018/05/05(土) 12:19:01.91ID:y1NIMmWz
Cスタイルのキャストは強力すぎて、効果が分かりにくいので、モダンでは、そのキャストは、reinterpret_cast<const char *>(&n)って書いた方がいい。
2018/05/05(土) 12:23:53.42ID:LkKePK4y
winsowsにはC#コンパイラが標準付属してますが、C++コンパイラは標準付属してないんですか?
2018/05/05(土) 12:24:24.44ID:y1NIMmWz
つまり、その本は古い。温故知新とは言うが、Cスタイルのキャストの使用はモダンではない。
2018/05/05(土) 12:35:42.78ID:y1NIMmWz
>>726
訂正。
× reinterpret_cast<const char *>(&n)
○ reinterpret_cast<char *>(&n)

そのCスタイルのキャストは
const_cast<const char *>(reinterpret_cast<char *>(&n))と同じ。
下手なキャストはバグのもと。キャストは最小限に。
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況