◎正当な理由による書き込みの削除について: 生島英之とみられる方へ:
0からの、超初心者C++相談室
動画、画像抽出 ||
この掲示板へ
類似スレ
掲示板一覧 人気スレ 動画人気順
このスレへの固定リンク: http://5chb.net/r/tech/1542002113/
ヒント:5chスレのurlに http://xxxx.5chb.net/xxxx のようにbを入れるだけでここでスレ保存、閲覧できます。
何にも知らない0からの出発、超初心者のためのC++相談室
C99に準拠したCプログラムってC++コンパイラで完全にビルドできますか?
>>4 型キャストが必要な場合と、C++キーワードに引っかかるケースがあるから、コンパイルできるとは限らない。
例えば、classという名前の変数がある場合は、C++ではコンパイルできない。
void *型の変数にint *の値をキャストなしに代入しようとすると、C++ではコンパイルエラー。
>>4 C99モードにすればおk
$ gcc -Wall -std=c99 -lm round.c
>>5-6 ありがとうございます。
C99では未定義だがC++で定義・予約されている言葉なんかが引っ掛かってしまうんですね。
C99頃から互換性も無いし、別言語だからそうでも無いけど、どっちかと言うとCのprintfに影響受けてる言語の方が多いね。
どっち先に覚えても良いけど、Cのprintfは押さえておいた方がいい。
(ただ、経験的にC++のオブジェクト指向を覚えるにはJavaかC#から入った方がいいので、挫折したらそっちを一旦勉強する事を勧める)
今の最新の規格ならだいぶ使いやすくなってるはず
とりあえず変数にはconstを付けれ
C++とJavaのオブジェクト指向って、なにが違うのでしょうか?
>>13 C++は、new を付けたらポインタ型になるが、Javaはnewを付けたら参照型になる。
>>14 JavaよりC++のほうが難しいといわれるのは、ポインタがあるからっていう意味合いが大きいんでしょうか?
>>15 C++のポインタは癌だ。どこにでもアクセスできてしまうし、メモリーリークが起きる恐れがある。安全ではない。
チェック付きの配列とスマートポインタを使えば、少しは安全になるが、完璧ではない。
まず、ポインタ変数の宣言が初心者殺し。
int* a, b;の場合、bはポインタではない。
関数ポインタはさらに文法が複雑すぎる。
関数ポインタ型の複雑さから逃れるには、typedefを使うとよい。
ポインタ型をtypedefしまくった環境がWindowsのWin32 APIだ。
intを大文字でINTと書く。intのポインタをLPINTと書く。unsigned intをUINTと書き、そのポインタをLPUINTと書く。
基本的な関数型は全てtypedefで定義済み。
これなら、ややこしいアスタリスク記号(*)に戸惑う必要はない。
型を大文字で書くと分かりやすいという意味で、Win32ではよく使うポインタ型を全て大文字で定義している。
char *にはLPSTRを、const char *にはLPCSTRを用意している。
なんてことを昔の人は考えたが、当然スマートポインタのほうがより安全である
>>15 >>14じゃ無いけど、個人的にはfriendクラスとかJavaには無いクラス同士の関係があったりするが最初はそれがどう言う関係か理解出来なかった。
Javaでオブジェクト指向に慣れた後理解出来た。
C++はそう言う独特のオブジェクト指向があるので、まずそこまで複雑じゃ無いオブジェクト指向言語で慣れる方がC++独特のオブジェクト指向の理解に繋がる。
>>18 無駄に覚えることを増やす馬鹿言語
wsとかswとか_sとかいっぱいつけやがってシッチャカメッチャカ
あとtypedefしてる型を型チェックのときに同一とみなすのが意味ない
せっかく型を別けてるのに
整数を定義するときって以下の3つだとどれがメモリ消費量とか実行速度の面で一番効率いいですか?
#define XXX (1234)
enum{ XXX = 1234};
constexpr int XXX = 1234;
>>24 今時のコンパイラならどれも同じになるだろうけど、#defineはただの置き換えだから、実質直接数字に置き換える。
お馬鹿なコンパイラなら、これが一番速い。
(メモリ上のXXXに格納された1234をレジスタに読むのじゃ無く、レジスタに直で1234と書き込むので、メモリアクセス分は速い)
constexprが候補に上がる時点で最新のコンパイラだと思われる
AIの力でコンパイラの性能を上げるって可能ですか?
a = xxx;
a = yyy;
これは、二重定義になりますか?
解決方法として
a = ("xxx" && "yyy");
を考えているのですが、これで良いでしょうか?
整数型とbool型を比較したり代入しようとしたときに警告かエラーを出す方法はありますか?
int i=5;
bool b=true;
i=b;
if(i==b)
if(i)
↑3行すべてでエラーなり警告なりを出してほしい
b=i;とif(b==i)は警告が出ます
環境はvs2017です
>>34 C++のboolのサイズはcharと同じだから
b=i: で警告になるのは整数型と論理型の変換というより単にサイズの小さい方に
代入しようとしたから警告になるてことだろうね
boolを使わずに Booleanクラスとかを自分で作れば型変換の許可/不許可も自在だけど
ま、やらんわな。そんな非効率なことは
34です
遅くなりましたがありがとうございます
自作クラスを作ってまでエラー出したいものでもないので気にしないことにします
MSがC++をCより勧める利点ってなんでしょう。
.NET関連で商売する為にC#などの利用を推奨するのは理解できるのですが
C++に拘りC99にすら対応しないのは何かよっぽどの理由があるのかなと思ってしまいます。
.net以前はMFCで商売してたからね。
その遺産を保守するのにC++が必要。
今でもそう言う会社相手に商売してる。
今はまだマシだけど、開発環境独占だと標準規格無視してた。
対応しなくても売れるのに、対応する必要は無いわな。
enum EN { yama,kawa}
をアクセスする規則がわかりません。 EN.yama の時もあれば 単にyamaの
時もあります。規則はどうなってるんでしょうか?
win16からwin32への移行では役に立ったのかもしれない。
c++相談室だぞ
習わなくていいなんて答えるヤツはいないぞ
いやCの勉強なんてしなくていいよ
最初からC++の勉強をすればいい
C++って便利になってもゴチャゴチャしてて汚い言語だとどっかで聞きました
ゴチャゴチャだと?
無理して拡張された機能を使わなければいいだけの話じゃないか
C言語でオブジェクト指向プログラミングをしようとするとどれだけ危険で汚くなるか分かってるんだろ?
C++は表面的にだけどそれをきれいにまとめた点だけでも評価されていいんじゃないか?
つまりテンプレートを使うなということですね判ります
c++は元はクラス形オブジェクトシステムを高速に動作させる為に始めたけど
今は単に高速にする事を目的に作っている様に見える
その為に一度に出来る様な記述を追加していってて有る意味便利なんだけど
機能が増えすぎて正確に把握するのが大変
その影響で何処か間違うとその間違った部分とは違う部分が違ってて
それを理解するのが大変
あちこちが絡みすぎてて言語自体がスパゲッティになってる印象
大量の事項を正確に覚えてそれられを正しく組み合わせないといけないから大変
超初心者にはかなりきつい
プログラミング初心者がやる様な物ではない
ある程度他のプログラミング言語をやって出来るようになってからの方が多分良い
>その影響で何処か間違うとその間違った部分とは違う部分が違ってて
>それを理解するのが大変
「何処か間違うとその間違った部分とは違う部分が違っててそれを理解するのが大変」
はその通りだが
「その影響で」
は関係無い
大変なのは今に始まったことじゃない
高機能ωになる前からずっとそう
この板にはC++委員会で多くの人が使いにくいと思っている仕様を提案してしまった
人が来ているので、最新のC++がダメになった、などと言うのは禁句。
>>52 STLに関しては、コンテナ以外の部分を使わなければ、かなりスパゲッティー感が
なくなる。C++98以降、STLの実装にしか使わないような template の機能強化
に邁進してしまったようだ。しかし、C++ reference などで STL がふんだんに
使って説明されてしまってるので若い人の間で STL が C++ の標準だと
思われてしまい、そこが難しいので C++ が嫌われる結果となっている。
本来はライブラリはプログラミングが簡単になることを目的にしているはずなのに、
STLはその逆を言ってしまっている。
問題なのは、STLを使いまくったC++コードがネット上に増えてしまっていること。
STLのコンテナ以外の部分とか自作template使わないとプロ感出ないからね
仕方ないね
言語仕様を一通り学んだ後でライブラリの詳細な使い方を覚えていけるのが理想。
ところが、cppreference では、言語仕様を本文だけでは説明し切れておらず、
サンプルコードを見てやっと理解できるようになっているが、そこで
非常に難解なSTLの使い方をしてしまっている。それでは
STLの非常に詳細な仕様を知らないとSTLの基礎となっている言語仕様すら
理解できないことになり、ある種の「トートロジー」のような現象が起きてしまう。
前段階の理解を元に三段論法的に論理や理解を進めていくという説明の仕方になっていないのだ。
そのやり方が C++ が難解であるというイメージを植えつけてしまっている。
cppreference の執筆者やC++委員会の上の方の人の中に、STLをC++の言語
それ自体だと思っている人がいるように思えてならない。
確かにPythonやRubyでは、似たような機能を持つものが、言語そのものの一部
である位置づけになっている。しかし、その理解はとても容易である。
だから、言語仕様を説明するサンプルコードがその理解を前提にしていたとしても、
理解の妨げにはならない。ところが、C++ではその事情は一変するのだ。
>>60 正確には、トートロジー というより、循環論法に近い。
>>60 たとえば cppreference のどの記事のことを言ってるんですか?
1つか2つでもいいんで、具体例がほしいです。
>>63 もしかしたら
>>60 の説明は「ずれて」いたかもしれないけど、例えば、言語仕様の
サンプルコードに高頻度に vector が出てくるので、それ自体がどうやって実装されているかを
調べることも重要になってくる。すると、initailizer-list なるものが重要であることがわかり、
vector の実装でそれがどう関係しているかも知りたくなる。それを知る前にまずは、vector template
の細かい仕様を調べたくなり、以下を見るとする:
https://en.cppreference.com/w/cpp/container/vector ↑は冒頭部分からしてこうなってる:
template<
class T,
class Allocator = std::allocator<T>
> class vector;
(1)
namespace pmr {
template <class T>
using vector = std::vector<T, std::pmr::polymorphic_allocator<T>>;
}
(2) (since C++17)
1) std::vector is a sequence container that encapsulates dynamic size arrays.
2) std::pmr::vector is an alias template that uses a polymorphic allocator
これは、初心者には難しすぎるし、実装を調べたいような上級者には情報が不足しており、
「帯に短し襷に長し」状態である(ちゃんとした説明になっていないのだ)。
上の部分を見た場合、最初に、allocator とはなんなのか、ということが疑問になる。
そして、allocator を調べなくてはならなくなる・・・・。
まず、vector とは何なのかが大まかに知りたかった人にすら、これでは難しい。
例えば、Ruby なら、[a,b,c] は、リストといって、集合です、と説明して
わずかなサンプルでもその全体像が分かった気がしてくる。
それとは全然違うことになってしまっている。
>>64 誤:initailizer-list
正:initializer-list
vector の仕様を調べようとすると、(1),(2)の2つの定義が出ており、(2)では
なぜか、namespace pmr が出てきて、さらに、using vector = ・・・、で
vector という名前が alias で定義されているらしい。基礎の基礎を知りたくて
vectorを調べたのに、namespace と using alias が出てくる。そして、pmr
という namespace がいったい何なのかということを知る必要が出てくる。
まず説明に言葉が足りてない気がする。英語は曖昧さを含み易い言語らしく、
英語に強い人に聞いても「文脈でどっちとも取れるので正確な意味は分からない」
と言われる。日本語に比して言葉の意味が薄くて、サンプルコードが重要となる。
IntelのCPU命令のマニュアルだと、擬似コードで説明されている事があり、
その場合にはほぼ正確に言っていることが分かるが。cppreferenceはそれもない。
ほぼ、サンプルコードだけが頼りになっているが、そのサンプルも分かりにくい。
サンプルに対する英語の説明が少なすぎるから。
>>64
時々、「コードこそがドキュメント」などという人がいて、それに従って
cppreferenceが書かれてしまっている可能性がある。しかし、vectorの
「仕様」とは、vectorが如何に実装されているかではなく、如何に使うか
の説明から入るべきなのに、>>64は、実装をモロに見せてしまってるから
難しくなっている。(1)のtemplate文だけでは、templateの仕様がまだ理解できてない
段階では、vectorの仕様を知ることが出来ないことになる。そう書くよりも、
いきなり、
std::vector<int> v = {7, 5, 16, 8}; // (100)
で、4つの整数型の要素を持つ配列を確保します。
メモリ上で要素は、隣り合わせに並びます。
配列の長さは動的に変更することが出来ます。
と書いたほうが良いし、完全な referece を書きたい場合でも、>>64 の(1)のように
書くべきではなくて、例えば、(100)を一般化して
[vector 型オブジェクトの作成方法]
std::vector<int> オブジェクト名 = 初期化子; // (101)
初期化子 := {初期値リスト}
などと書かないいけない。
>>64 の (1)は、vector自体の「実装方法」を書いているだけで
vectorの「仕様書」にはなっていない。 なるほど
それならトートロジーとか循環論法と言うよりも
もっと適切な言葉があるはず
>>66
集合や、データベース系のソフトウェアでは、言葉は忘れたが、
初期化、追加、削除、参照、検索、個数の取得
などが良く使われる(ほぼ必須の)基本機能だとされるから、
[vector 型オブジェクトの作成方法]
std::vector<要素の型> オブジェクト名 = 初期化子; // (200)
std::vector<要素の型> オブジェクト名 初期化子; // (201)
初期化子 := {初期値リスト}
[vector 型オブジェクトへの末尾への要素の追加]
オブジェクト名.push_back(要素); // (210) 要素をコピーして追加したい場合
オブジェクト名.push_back(std::move(要素)); // (211) 要素を移動して追加したい場合
[vector 型オブジェクトの idx 番目の要素の参照]
オブジェクト名[idx] // (220) : idx は先頭が 0 から始まる。
・・・
などと書いていけばよい(自分は細かい仕様が分かってないのでこれ以上詳しくは
書けないが、reference manual を書く人なら書けるはず)。
初心者が期待する reference manual とは上記のようなもので、
>> 64 のようなものではない。何度も言うが、>>64 は
実装と仕様が混合されてしまったもので、どっちつかずの状態になっている。 大きい・小さいとか、言葉は、about で抽象的だから、
こんな厳密な事を決めるのには、向いていない
図解・サンプルの方が、圧倒的に理解しやすい。
だから、下の3冊などは、神の書と呼ばれる
サンプルを示すことで、OK/NG というのがハッキリわかるから!
C++11/14 コア言語、江添 亮、2015
組込み開発者におくるMISRA‐C:2004―C言語利用の高信頼化ガイド、MISRA‐C研究会、2006
Linux プログラミング・インタフェース、Michael Kerrisk、2012
理解できないような事を書いている、香具師が悪い。
そういうのを追っかけても、時間の無駄
プログラミング・フレームワーク・構造がわかるためには、Ruby でもやった方が余程よい。
C/C++ などポインタのある言語は、プログラミングを学ぶのに適していないし、
バグで時間を浪費するから、結局学べないw
なるほどね
初心者にとっては
一度に多くのことを覚えないといけないのは負担が多い
生配列を使うのは良くないから最初からvectorを教えるのは
有る意味正しいけど
理解するには難易度が上がってしまっている
オブジェクト指向プログラミングでも同じ様な感じで
例の
動物クラスから継承して犬猫クラスを作ってワンニャン
とかの説明とかが良く有るけど
機能の説明としてはそれでいいんだけど
実際にそういう風には作らない(別にそういう風にやりたきゃやってもいいけど)
実際上は別な構造として作ったりするんだけど
その別なやり方をどうするのか?という説明が殆ど無いので
オブジェクト指向は糞
みたいな話になってくる
唯一の例題として有るのが
デザインパターン
だと自分は思っているが
あれを意味が無い
とか言っている人が結構居て
そのせいで軽視されているのが残念というか問題だと思ってる
初心者が手がかりにするのは難しい面も有るけど他に良さそうな例題が余り無い
適切な教科書を作る
というのは結構高度で大変で
作れる人が少ない
その割には作った人には余り金にならなかったりして
作ってくれる人が余り居ない印象
gcc も g++ も VC も肥大化し過ぎた
digital mars c とか Borland C 5.5 かそれよりもっと前
tiny c compiler でもいい
初心者用にはもっとシンプルな C で充分
>まず説明に言葉が足りてない気がする。英語は曖昧さを含み易い言語らしく、
英語は抽象意味言語だから指している範囲がザックリしてて
短い文章とかだと何を言っているのか解らない
その分覚えておかないといけない分量が少なくて良い
英語から日本語に自動翻訳を掛けても上手く翻訳されていない時はその文章が何の分野で有るか解らないから間違っている様に見えると感じる
日本語は一つの意味を指している事が多いけど覚えておかないといけない分量が多いから大変だけど
その分広い範囲の意味を指していないのでちゃんと使うと意味が一点を指して誤解し難い
けどプログラムを書く時は
javaだととりあえず.を書いておけば良いから迷わないけど
c++だと.だったり->だったり::だったりするから迷う事がある
そんなに致命的な問題では無いけど
入門ロベールC++の188ページに
const char* MONTH_NAME[]={"睦月,"如月,"弥生"......
というのがあるのですが、なぜchar*型の前にconstをつけると文字列リテラルをたくさん代入出来るのでしょうか?
const定数を外すと同じことが出来ないのがよく分からないです。ポインタが理解できてないのでしょうか。
それの場合MONTH_NAMEの型は
「書き換えられないchar」「へのポインタ」「の配列」
であることがわかれば後はわかるっしょ
>>78 すいません、分からないです・・・
何が分かってないからこうなってるのか。も分かってないからまた読み直して同じページに戻っても理解できないです・・
>>77 文字列リテラルの指す文字列は書きかえてはいけない。
char* の指す先の文字列は書きかえできる。
const char* の指す先の文字列は書きかえできない。
>>77 あーわかった。あんたがエラーメッセージを読んで理解しようとしないから分からないんだよ。
分かりません。
ポインタを直接文字列の値で初期化してるのもよくわからないです。
char *s = "abc"; がダメな理由と
int a[] = { 1, 2, 3 }; がOKな理由を考えろ
const char* MONTH_NAME[]=
型 変数名[]
各要素の型は、const char*
[ ] は配列
最近、ロベールは本屋で売ってない
Ruby なら、変数名はラベルだから、変数に再代入できるけど
a = "a"
a = "abc"
>>84 char* sはchar型の変数の参照が入ってないから駄目なのでは?
下はただの配列変数だからできてるのでは?
>>85 const char*という新しい型があるのですか?
constとは定数を宣言するだけのものじゃないのでしょうか
char* str[]={"aaa","bbb","ccc"}はできないのに
const char* str[]={"aaa","bbb","ccc"}はエラーにならないのも意味わからないです
const chr*のエンティティ云々も意味不明なのですがロベール188pまでにその説明は載ってるのでしょうか
じゃあ const char *s = "abc"; がわからないのか
これはどこかにある "abc" という配列へのポインタでsを初期化しなさいっていう意味で、
char *s = "abc"; がダメなのは "abc" が変更不可だから
あとは const char *s = "abc"; と const char *MONTH_NAME[] = { "睦月", ... }; の関係が int i = 0; と int a[] = { 0, ... }; の関係と同じであることを考えればわかるはず
>>89 「できない」理由はエラーメッセージに書いてあるだろ。読めよ。
>>90 文字列って定数なんですか?
何となく分かってきた気がします!細かく教えていただきありがとうございます
>>77 const 付けたくないなら
char MONTH_NAME[][5]={"睦月,"如月,"弥生"......
char r[] = "hoge";
char *s = "hoge";
const char *t = "hoge";
char *MONTH_NAME_A[]={"睦月","如月","弥生"};
char MONTH_NAME_B[][7]={"睦月","如月","弥生"};
どれもエラーも警告も出んかった
char *t = "hoge";
これがエラーにならないのは言語上の欠陥
ロベールさんで紹介してる環境に限定されると語れる立場じゃないんだが…。
>>93 漢字1文字を2byteと仮定するのは危険じゃないかしら。
このごろUTF-8でベタに文字列書くことが多いんでちょい気になる。
と言ってu8プレフィックス付けるほどお行儀良くもない中途半端な人。
>>94 char *s = "hoge"; で警告出ないとは
ストラウストラップ先生がガッカリしそうなコンパイラね。
>>95 C++11 以降の言語仕様では許していない。
それより前の仕様では許していたという歴史的経緯があるので
(エラーではなく) 警告にとどめている処理系がまあまあ有るという事情。
ロベールの入門書に /*構造体変数student*/
int length = sizeof stundent /sizeof *student
というのがあるのですが何故これで配列の要素数が出るのでしょうか?
sizeof student / sizeof student[0]だと配列の要素数が出る理屈は何となく分かるのですが
配列とポインタは別のものですよね?
student[0] と *student は同じ
何で同じなのでしょうか?これで動くからこういうもの。という理解で大丈夫なんでしょうか
とりあえず stundent は誤りで正しくは student だとして
多くの場合、配列名は「配列の先頭要素を指すポインタ」と解釈される、から。
つまり配列studentについて student == &student[0] が成り立つ。
*演算子を作用させて *student == *&student[0] == student[0]
よって sizeof *student == sizeof student[0]
ここで注意すべき点は「配列名がsizeof演算子のオペランドになった場合は
配列の先頭要素を指すポインタとは解釈されない」ってこと。
sizeof 配列名 == 配列全体が占有するメモリ容量
なぜそうなっているか、という理由は「そう決めると便利だから」かな。
Cの頃からそういう感じでプログラム書いてたから、という歴史的経緯もある。
>>102 初心者をからかっちゃアカンよ。信じちゃうかも知れん。
コロチャンもゲイツの陰謀とか言ってる人が居てわろす
温暖化も陰謀ω
>>99 「暗黙の型変換」によって配列がポインタに型変換されるルールがある。
スムーズにポインタとして使えてしまうから混同してわけわからんようになる初心者が多いんだけど、
あくまでも別物であるという理解が出来ているなら入門者としてはかなり優秀だと思う。
ほとんどの場合に配列はポインタに暗黙に型変換されるんだけど、
例外としては
@ sizeof を適用するとき
A 単項の & を適用するとき
B 参照で受け取るとき
があって、これらの状況では型変換されずに解釈される。
----
余談だけど暗黙の型変換とは別に仮引数の調整というのもあって、
関数の仮引数として配列を書いた場合も配列はポインタに調整される。
たとえば
void foo(int a[10]) {}
という定義を書いたら
void foo(int* a) {}
と全く同じように解釈される。
すいませんロベール持ってる人にお聞きしたいのですが
305ページの
for (int i = 0, size = a.Size(); i < size; ++i) という文があるのですが
このsizeというローカル変数は何処に定義されてるんでしょうか?
>>106 “ロベール本”を持ってないので答えられない立場かも知れんけど…。
この size は「ここ」で定義されているんだと思うよ。
for の初期化式 int i = 0, size = a.Size(); で、
「int の i」と「int の size」という2つの変数を定義している。
>>107 forの中で2つ宣言できるんですね!そんな事も知りませんでした。
ありがとうございます。
型が違うときは?
for (long i = 0, int size = a.Size(); i < size; ++i)
C++17なら
for (auto [i, size] = tuple(0L, a.Size()); i < size; ++i)
class DataStore {
public:
DataStore(int v) : mValue(v) {}
bool operator==(const DataStore& rhs) const;
private:
int mValue;
};
bool DataStore::operator==(const DataStore& rhs) const
{
return mValue == rhs.mValue;
}
int main()
{
DataStore ds1(10), ds2(10);
if (ds1 == ds2) {}
}
というのがあるんですがoperatorに記述されてる仮引数はどっから実引数をコピーしてるのですか?
後演算子のオーバーロードに関して分かりやすく解説してるとこあれば教えていただけると嬉しいです
operatorも、ただの関数
if (ds1.operator==(ds2)) {}
const DataStore& rhsの実引数はds1ってことですか?
この流れだと、仮パラメータ rhs にバインドされる実引数は ds2 でしょ。
クラスのメンバ関数として宣言された2項演算子の operator OP(rhs) は、
lhs OP rhs と書くと lhs.operator OP(rhs) が呼び出される。
…と書いても分かりにくいね。
具体的には ds1 == ds2 と ds1.operator==(ds2) が同じ意味、
ってのが
>>112 の人の言ってること。
余談だけど左右の引数が const な比較演算子は非メンバ関数として実装した方が好ましい場合が多い。
(標準ライブラリでもだいたいそうなってる。)
なぜ文字から'0'を引くと数字を数値に変換できるのですか? char c='8' int a=c-'0'
理屈がよくわからないです。
よろしくお願いします
文字コードが順番に並んでるのは分かったのですが
なぜ'0'引くとキャストせずにint型の変数に代入できるようになるかが分かりません
よろしくお願いします
'0'を引かなくてもキャストせずにint型の変数に代入できるよ
c/c++では文字は整数型に文字コードを入れて扱うんだよ
苦しんで覚えるC言語という本の255ページに
”数字を使うときには引き算で本来の数値を知ることも出来ます。
数字に持っ文字の番号が割り当てられており例えば'0'は48番に割り当てられてます。
数字から'0'の番号を引き算すれば数値に変換され計算に使用できます。”
とあるんですが
”数字から'0'の番号を引き算すれば数値に変換され計算に使用できま”というのが意味わからないです
文字が元々数値(文字コード)であることが理解できてないのでは
ASCIIコード表でググってみれ
2に3を足す時、
int a = 2; int b = 3; int c = a + b;
とやるとc == 5になる
int a = '2'; int b = '3'; int c = a + b;
とやってもc == '5'にはならない
今やほぼASCIIだからc == 'e'になる
int a = '2' - '0'; int b = '3' - '0'; int c = a + b;
とやるとc == 5になる
'0'から'9'まで連続していることはcの規格が強制してるから
これが”数字から'0'の番号を引き算すれば数値に変換され計算に使用できます”の意味
char c = '8'; // '8'を表す文字コードの値(ASCIIでは56) char型
// '0' ... '0'を表す文字コードの値(ASCIIでは48) char型
// c - '0' ... '8'を表す文字コードから'0'を表す文字コードを引いた値(==8) char型
int a = c - '0'; // char型の数値8 で int変数a を初期化・代入
一般にint変数にchar型の値を格納することは認められている。
思うに「'8' - '0' が 8 になる」('8'の文字コードでなく「タダの8」)
という部分に引っ掛かってるんじゃなかろうか。
すまん 124 は間違ってるみたい、忘れてくれ。
char c = '8'; // '8'を表す文字コードの値(ASCIIでは56) char型
// '0' ... '0'を表す文字コードの値(ASCIIでは48) char型
// c - '0' ... '8'を表す文字コードから'0'を表す文字コードを引いた値(==8) int型
int a = c - '0'; // 数値8 で int変数a を初期化・代入
思うに「'8' - '0' が 8 になる」('8'の文字コードでなく「タダの8」)
という部分に引っ掛かってるんじゃなかろうか。
'8' - '0' は「char型の8」ではなく「int型の8」だね。(以下検証コード)
std::cout << "sizeof('8') == " << sizeof('8') << '\n';
std::cout << "sizeof('8'-'0') == " << sizeof('8'-'0') << '\n';
>>125 そういうことでしたか。
詳しく噛み砕いていただきありがとうございます。
型の検証はC++11なら直接的にできるね。
#include <typeinfo>
...
std::cout << "'8' is " << typeid('8').name() << '\n';
std::cout << "'8'-'0' is " << typeid('8'-'0').name() << '\n';
実装定義の型の名前を得られる。
なかなか、適当なスレを見付けるのが難しいわい
C++ 且つ初心者だから、ここでいいのかな
subroutine で、例えば、boolean と string のふたつの変数の値を
return するには、やっぱり std::map を使うのが一番簡単でしょうかね?
あ、では、boolean, string, int の三つをreturn するには普通どうやるのが王道でしょうか?
たぶんそうだとお芋ます、ええ。
あと、コンテナに突っ込みたいときにはstd::variantなんかも良く使います。
今回は関係なさそうですが。
>>131 王道かどうかは知らんが、C++17以降なら
auto func() {
return std::make_tuple(a, b, c);
}
auto [f, s, n] = func();
っていう風にできるで
C++でint[変数]というようなことが出来ないのはstack overflow防止のためなんでしょうか?
>>136 原則として型は大きさが決まっているもんなので、そうでないものがあるとややこしいんだわ。
(配列の大きさは型の一部。)
>>138 新しいの……?
C99 で出来るようになったけど C11 以降ではオプショナル扱いなんだわ。
そして今年は 2020 年なんだわ。
以下のコードは比較関数をSTLのlistに渡す為のものなのですが
これを最新のVC++でコンパイルできるようにするにはどう書き直せばいいでしょうか?
typedef SubType* LPSUBTYPE;
template<> inline bool greater<LPSUBTYPE>::operator()
(const LPSUBTYPE& pObj1, const LPSUBTYPE& pObj2) const {
…
}
>>141 エラーメッセージを読んで問題点を解決するように書き直すといいよ。
list に比較関数は渡せないと思うので前提が間違ってそうな気もする。
VC++についての質問になってしまうのですが、C#のようにソースファイルをリンクとして追加することは出来ないのでしょうか?
C#と違って「既存の項目」で追加したものに関してはコピーされずに参照扱いだよ
作業フォルダ下以外のファイルをそうやって追加した場合は追加のインクルードディレクトリも設定しないとダメだけど
何で構造体のchar配列は直接値が代入できず
strcpyを使う必要があるのでしょうか?
できるよ
struct A {
int x;
char b[4];
} a = {0, 1, 2, 3, 4};
typedef struct {
char str[32];
}A;
int main(}{
A a;
a.str="aaa";
}
これができないってことです
言葉足らずですいません
int main(void) {
int arr[5];
arr = 3;
}
ができないのと同じ理由です
ちょっと忘れたから、推測だけど、
a.str="aaa";
"aaa" を右辺で使うと、先頭要素のアドレスに変換されるとか?
例えば、4バイトのサイズで、10〜13 アドレスに存在する場合に、10が代入されるとか
char str[32];
一方、ここにはアドレスじゃなくて、aaa\0 という4バイトの実体を代入しないといけないとか
意図してるだろうことを無理してやるなら
str[0] = 'a';
str[1] = 'a';
str[2] = 'a';
str[3] = '\0';
でできる.そしてこれをするためにstrcopyがある
出来ない訳じゃないんだよな
typedef struct {
char b[4];
} A;
int main(void) {
A b = {1, 2, 3, 4};
A a;
a = b; // ok
a.b = b.b; // bad
return 0;
}
自分で for で配列要素代入すれば良い訳で
面倒だから memcpy や strcpy 使ってるだけ
>何で構造体のchar配列は直接値が代入できず
構造体のchar配列だけじゃなくて
ただのchar配列でもダメだろ
宣言と同時に代入してるときはたまたま出来るだけ
int main() {
char a[4] = "abc"; // OK
char b[4];
b = "abc"; // BAD
return 0;
}
>char a[4] = "abc"; // OK
これがおkなのは、cの言語仕様におけるほんの雀の涙猫の額ばかりの文字列サポート
たまたま、ってw
はじめたころは、こういうことにいちいちひっかかってたな…
わかっちゃえば、慣れちゃえばどーってことないんだけど
同じようでいて、初期化と代入では見た目の作用がことなることがあるね
>>157 常に初心に返ることで新たにわかることもある
C#ですいません
usingとnamespace名前空間を使う意味について本で解説されてるんですが文字だけしか書かれてなくて
イマイチ言ってる意味がわからないので
簡単なコードを用いてnamespaceを使う意味を教えて欲しいです
>>165 すいません、そういうことです。
usingについてはおかげさまで意味が分かりました。ありがとうございます。
namespace名前空間?と言うもののメリットと言葉の意味がいまいち分からないのですが、
どっからどの部分までが名前空間なのでしょうか
>>166 namespaceがなかったら
たとえば自分でなにか作ってるときとか、そこには自作のメソッドの定義があるわけで
さらに公開されてるライブラリを使いたくなって、いざそこに組み込んだとき、
自作のメソッドと同名のメソッド名がライブラリ内で定義されてたらコンパイルエラーが発生する
(重複定義された場合はコンパイラからすればどちらを呼び出していいかわからない)
みたいな事態が発生してしまう
さっきの例だと同名のメソッド(Console.WriteLine)を定義してても
System名前空間とMyNS名前空間で分けたからコンパイルが通る
System.Console.WriteLine(s); // Console.WriteLineはSystemに属するもの
MyNS.Console.WriteLine(s); // Console.WriteLineはMyNSに属するもの
namespace Hoge {
// {}内はHoge名前空間に属する
}
完全にC++の感覚でしか説明できんけど、
あるライブラリを開発する上で、そのライブラリ全体がnamespaceで囲われていると、
ライブラリ作者は大抵その名前空間内でコードを書くから、いちいち名前空間を指定する必要は無い
さらに
>>164の言うように、名前空間がライブラリや機能を表しているから、その中のコードは短い命名に出来る
ライブラリ利用者側からすると打鍵数は変わらない(か、下手すると増える)けど、その名前をよく使うソースコードなら、usingで取り込むことも出来るし、あまり使わないなら取り込まず毎回指定してもいい(その場合名前重複の心配もない)
こういう取捨選択は、関数・クラス名に全部ライブラリ名や機能名のプレフィックスが付くような命名だと出来ないこと
あと_privateみたいな名前空間に関数を書けば、ユーザーが触る必要の無い関数を隔離出来る(使用を禁止までは出来ないけど、補完の候補に出てこないのは便利
名前空間を使うと検索性が最悪になる
(別の名前空間の同一名称が引っ掛かりまくる)
みんなどう対処しているんだろう
>>169 using namespaceするのが問題じゃない?
いやusingに限らず、例えば
>>168で言ったライブラリ作る側(名前空間内で作業する側)はいちいちhoge内なのにhoge::とか書かんでしょ
確かに検索で困ることはたまにある・・
namespace で絞り込んで、識別名をハイライトして、あとは気合
C++とVisual C++の違いについてです。
C++はプログラミング言語であり、
VC++は統合開発環境であるという説明があります。
でも私にはVC++がC++++のように見えます。
VC++はC++の文法に新たな流儀を付け加えるか置き換えていて
言語そのものの使用を若干変えているように見えます。
C++のキーワードが別のものに置き換わっていたりするからです。
そのため、C++を勉強したあとにVC++を学ぶと違う言語を学んでいるように感じます。
この理解は正しいでしょうか。
多少違うのは
#pragma くらいだろ
勝手に仕様なんて変えない
統合環境とか API とかはもちろん関係無い話
IDEはVisual Studio
VC++はMSのC++商品名
C++/CLIとかを混同してね?
これはC++を独自拡張したものだよ
__declspec(dllimport)とかアホみたいに書かされたあの時代のmsvc拡張c++のことでしょ
C++/CLIは拡張ですか?
いくつかの流儀を置き換えていますよね?
ポインタをハンドルと読んだり?
MS拡張にしろC++/CLIにしろ既存のコードの挙動を変えるようなことはしてないんでは?
拡張でいいんじゃね
Visual Studio 2019をインストールしました
Windowsスタートボタン→Visual Studio 2019を起動しました
プロジェクト名を入れて下さい→test001
保存フォルダの場所を決めて下さい→Y:\_source\repos
何かのウインドウが開きました(おそらく開発の統合画面?)
さっそく1行目から入力しようとしましたが、キー入力を受け付けてくれません
左の縦に、ツールボックスと表示しています
このままでは進まないので、エクスプローラーでreposフォルダの下に
samp01.txtを新しく作りました
何かのウインドウに戻り、samp01.txtを開くと文字入力が可能になりました
進め方が間違っているように思えますが、samp01.txtに#define...から
描き始めてよいでしょうか?
統合環境が苦手で、フォルダにテキストファイルを作りテキストエディタで
ソースを書いて保存
コマンドラインでコンパイル、エラーがなければリンク...をしてきました
何かの画面には難しそうなソリューションエクスプローラー、その下には
プロパティウインドウが表示されています。
このウインドウにも慣れないといけないので進め方を教えてください
>>182 俺は、テキストエディタでソースを書いて、c規格で拡張子cppで保存して、
Visual Studioで、
コード無しで続行→
ファイル→開く→フォルダ
で、コンパイルしてますがね。
>>182 ソリューションを作るときに大雑把にどんなもの作るって指定すれば
最低限のファイルができて編集可能な状態になるんじゃないの?
ソリューションエクスプローラーのヘッダーファイル、ソースファイルのとこを右クリックで新規選べばまっさらなファイル作れるし
メニューのファイル→追加?(うろ覚え)でも作れる
手順書のページのURLありがとうございます。
Microsoft Visual Studio Community 2019
Version 16.8.2を使用中。
テキストで#include<stdio.h>から入力しましたが煮詰まりました。ソースはネットを検索してコピペなので、
コロンやセミコロンの間違いはないと思われます。
#include<stdio.h>
int main( void )
{
printf( "ようこそC(++)言語の世界へ\n" );
return 0;
}
タスクバー?にファイル(F)編集(E)表示(V)Git(G)プロジェクト(P)デバッグ(D)テスト(S)・・・があります。
手順書では[プロジェクトをビルドするには、 [ビルド] メニューの [ソリューションのビルド] を選択します。]とあります。
が、ビルドメニューがありません。
プルダウンのデバッグ(D)からデバッグ無しで開始したいですが
デバッグ無しで開始が薄い文字になっており、クリックできません。
統合開発環境って皆さんが使用して使いやすいはずですよね。
何から順番にクリックしていくのかさっぱりわかりません。
手順通りにしようとして「ここをクリック」のところはたいていその「ここ」の項目が画面になくて
ソースを書いてコンパイルすらできない、ありません。ありません状態。
同じバージョンでもメニューの項目が違っていたら次に何をするかお手上げです。
お助け下さい。
>>187 ソリューションを作成した?
ソリューションにソースを追加した?
アドバイスありがとうございます。
ソリューションエクスプローラー フォルダービューを右側に開いています
そこにhello_.cppが表示されています。いま、開いているファイルです。
#includeからreturnまでペーストしています。
ソリューションエクスプローラーでhello_.cppを右クリックしますと[追加]があります。
[追加]->新しいファイル
新しい項目の追加(W)
新しいフォルダー
この3つを表示します。ソリューションエクスプローラーにhello_.cppが表示されているだけでは不足でしょうか
hello_.cppを右クリック新しいファイルを選ぶと名前を入力になりました
aaaと入力するとツールボックスに新しくテキスト入力タブが表示
#includeからreturnまで貼り付けました
デバッグ無しで開始の文字は薄いままです
ビルドメニューはありません
編集や表示、Git、プロジェクトのメニューを色々クリックしています
変わりません…
何か、こんな不自由な統合開発環境を使うのは苦痛しか感じず、しかし
全世界のプログラマの人たちも使っているものですし、なんとか
ビルドメニューを出したいです
あちこちクリックしていますと、画面の上に
プロジェクト、ビルド、デバッグの文字が出てきました
ビルド->ソリューションでコード分析を実行を選びます
デバッグ->デバッグ無しで開始は薄い文字でクリックできません
何か手順が不足しているようです
ファイルとフォルダの違い
ソリューションの種類が違う
だろうな
不慣れでごめんなさい
デバッグ無しで開始は薄い文字でクリックできず変わらず
本日はそろそろ寝ます
後は明日、使い方と用語を調べます
初心者は素直にチュートリアルの手順に従ってればいいんだよ。
「何かしたい」というものが無いならば、しなくてどうぞ。
「何かしたい」というものが有る人は、自分で行動する。
質問サイトにある質問に (根拠になる一次資料 (主に仕様書の具体的な項目) と共に) 回答するのを繰り返せば
特定のプログラミング言語に詳しくなることは出来るよ。
それでプログラミングを出来るようになるかどうかはわからんけど。
「人工知能搭載の人型アンドロイドが作りたい」
という目標を持つ者が
「printfで文字列を表示したい」
という目標を持つのはとてもつらい
国会図書館は国会議事堂内に分室があって資料を取り寄せて閲覧できるんですよ。
でも、ほとんど利用実績が無いらしいんですね。
国会図書館は若い女性と、男性は老人が多かったです。
土曜日だからかもしれません。
資料のコピーは長蛇の列が出来ていました。
あの列で感染するんでしょうね。
女性のメガネ率は8割超えてました。
おそらくドクター持ちでしょうね。
m1 macbookでc言語始めるのには何が必要ですか?
c言語を始めるパッケージとかって売ってるんですか?
それともフリーソフトでダウンロード出来るんですか?
学校ではコマンドを打つところから始めたので、導入に関しては全く解りません。
>>202 clang、gccなどのCコンパイラのインストールが必要。
>>204 レスどうもです
gccほかググってみました
@エディタで入力
Aコンパイラで2進数へ変換(ここでgcc使用)
Bコマンドプロンプトで実行
これで合ってますか?
合ってるとすれば、エディタは何がいいんでしょうか?
>>205 Macは異端児だし、自由陣営じゃないから、テキストエディタは自分で選んでね。検索するときは、必ずキーワード「Mac」を付けてね。
コマンドプロンプトはWindowsの場合なんだよな。
Linux なら、build-essential で、Ruby のRake でコンパイルする。
VSCode も使える
mruby の本も出た
Webで使えるmrubyシステムプログラミング入門、近藤宇智朗、2020/11
宇宙開発などの組み込み用、MicroPython, Lua, Squirrel の代替になる。
Ubuntu 18.04, C99 対応
人工衛星イザナギ・イザナミで、使っている
MacでもVSCode、gcc、terminalでええやんけ
色々教えてもらってありがとう
でもなんかrubyから始める方が良さそうなのでそうします
Mac で、Cをやる人なんているのか?
たいてい、Linux だろ
Macの機械語をもらっても、誰も動かせないw
一応Visual Studio Community for Mac
何てものもあるけどね
MacユーザーじゃないのでWindowsと同じように使えるのかどうかは知らんけどw
大昔のmacbookの話だがxcodeなる10GBくらいの開発環境を入れないとほとんど何も弄れなかった記憶
今のストレージ容量ならmacbookでも行けそう
winは仮想環境も充実してるし色々コンパイラ試せるからいいよね
ネイティブサポートもintel mklやVCで結局一番手厚いし
>>207 F-15はAda、F-35はC++で書かれてる。
Linux には、strace という神ツールもある
>>215 それでもApple環境だけはきついのよなぁ
噂通りiPadにxcode載せてくれれば、俺的に余計な出費なしに楽しめたのに
(もちろんiPad自体で開発する気はない)
>>213 普通に使えるはず
VSとか勧めるくらいなら(IDE勧めるなら)macにはxcodeのが正しい
M1 macbook買ってruby でうっほっほーしてますわ
最近コード読まなきゃならん機会増えてきて教養として読めるようにはなりたい
規格に沿ってなくても勉強にいい感じのインタプリタってないかな?
プロになりたい香具師は、YouTube で有名な雑食系エンジニア・KENTA のサロンに入って、
16〜32GB メモリのMac で、Ruby on Rails でポートフォリオを作る
もっと、すごい人は、Windows 10, WSL2, Docker, Ubuntu, mruby で、
C99/Ruby 併用で、人工衛星など宇宙開発してるw
mrubyの本も出たし
srand((unsigned)time(0UL));
int r=rand()%100-1;
ってコードがあるのですが返ってくる値がランダムじゃなくて規則性があってモヤモヤしてます
参考書によるとsrandの文が起動時に別の値に毎回変えるための文らしいんだけど
返される値が8,18,28,28,38,48.......と10ずつ繰り上がっていってランダムになってません
何を追加すれば規則性が消えるでしょうか?
>>226 0 以上 99 以下 の乱数を取得したいなら、
int r = (int) ( ((double)rand()) / ((double)RAND_MAX + 1.0)) * 100.0 );
0 以上 98 以下 の乱数を取得したいなら、
int r = (int) ( ((double)rand()) / ((double)RAND_MAX + 1.0)) * 99.0 );
>>226 疑似乱数は一定の規則に従って生成されるんだから規則的なのは当たり前。
それがどのくらいわかり難いのかという程度問題に過ぎないし、
どういった系を選ぶのが適切なのかは用途次第。
そしてよくある失敗だがランダムシードに時刻を使うなら時刻から予測できる可能性がある。
rand がどういうアルゴリズムで乱数生成するのかは言語仕様では規定していないけれど、
(乱数がとりうる範囲や、同じシードからは同じ乱数列が得られるという性質は規定している。)
伝統的に線形合同法で実装されることが多くて、
パラメータの選定や用途によっては露骨に規則的に見えることもある。
C++ では
>>229 の言う通りメルセンヌツイスタが標準ライブラリとして提供されているのだから
それを使うのは妥当な解決方法である可能性は高い。
とはいえメルセンヌツイスタは簡単な物理シミュレーションなどにはおおよそ十分であるにしても
暗号用途には使い物にならないし速度はやや遅いので乱数が大量に必要な場合には
適切とは言えない。
かといって本物の乱数 (環境ノイズなどから生成される乱数) は再現性がないし、
これもまた遅すぎるので大量の乱数が必要な場合には向かない。
繰り返すけが乱数は用途に適しているかどうかであってあらゆる場面で万能な方法はない。
用途次第、状況次第。
今C言語を学習してるのですがC++じゃないと完全ランダムは無理なのですね…。
RAND_MAXは関数なのでしょうか?Cだと使えなかったです。
教えてくださってありがとうございました。
何をやりたい目的があるから、何々を勉強するだと、速いですよ。
このスレは C++ スレだからな。
C++ は C との互換性のために残している機能はあるが C++ 的にあまり好ましくない場合もあるし、
完全な互換性が維持されているわけでもない。
>>232 RAND_MAXは、古くから有るマクロ定数で、stdlib.h で例えば次のように定義されている:
#define RAND_MAX 32767
説明によれば:
「rand関数が返す最大値。処理系によって異なるが、最低でも 32767以上である。」
rand()は偏りが強いには強いが、それでも 227 のように書けば 226 のように
下一桁がいつも8になるようなほどではない。
少なくともrand() は、
>>227 のように書けば、メルセデスツイストなどの
乱数を使わなくとも普通に使える。
>>226 のように書くとダメなだけ。
0から7の整数が均等確率で出る乱数をrとした場合、
x = r % 3;
とすると、xは0〜2までの整数が出るが、均等確率ではない。
それはすべてのパターンを書いてみると分かる:(r,x)を書いてみると、
(0,0)
(1,1)
(2,2)
(3,0)
(4,1)
(5,2)
(6,0)
(7,1)
x= 0 となっているのは、3回。
x= 1 となっているのは、3回。
x= 2 となっているのは、2回。
なので、
P(x=0)=3/8
P(x=1)=3/8
P(x=2)=2/8=1/4
となり、x=2が出る確率だけが小さくなってしまう。
これと同様に、rが0〜32767を均等確率で出す乱数の場合、x=r % 100の値は0〜99までだが
xが0〜99になる確率は均等ではない。
なので、もし、とても偏りの少ない乱数を用いたとしても
>>226 では均等に
出現しない。
それを解決するには
>>227のようにすればよい。というか227が標準的なrand()の
使い方。
227 だともしrand()が均等確率で出ているならば、結果も均等に出現する。
ちなみに、rand()は、出力範囲内の整数を全て出力し終わってから元の値に
戻る様になっているので周期も RAND_MAX + 1 に等しく、出力値は
均等確率で生じる。
>>226だと10で割った時の余りが必ず8になっておりそれは、出力が
10n + 8 になっているということ。これだと、今言った法則に当てはまって
ないので矛盾し、何かがおかしい。
>>243 バークレーソケットをオープンしてリスンして、接続してきたのなら fork() だのスレッドで処理だの、というのを昔したことがありますが、すっかりわすれてしまいました…
どんなサーバーが欲しいのですか?簡単なサーバーならご要望に応えてテキトーに書く準備はありますよ
>>241 それはよくある勘違い。
>>227 の方式では均等にならない。 櫛状にばらける。
0〜32767 の乱数から 0〜99 の乱数を得るには
32700 以上の値が出たときにそれを捨てて
そうでない値のときに 100 の余りをとればいい。
少なくとも私の手元の環境にある std::uniform_int_distribution はそのように実装されている。
>>241はアホと思ったけど、
こんな勘違いをするアホがよくいるって?
そんなアホな
>>246 uniform_real_distributionの時は?
>>226 の結果は予想と外れていると思う。
rand()は均等確率のはずなのに、100で割って下一桁に9ばかり出るはずはない。
>>246 なるほど。言われてみればそうだわ。
32767はもともと100で割り切れないから、一部を捨ててやらないと
均等にはならないな。
しかし、昔実験してみた限り、rand()の周期は、通常、RAND_MAX + 1
であり、rand()自体は均等確率のはずだ。
それはべつに、
>>246ではちみつが言っていることと矛盾するわけではない。
RAND_MAXが32767のように100で割り切れない値だから、
>>227 のようにすると、端数の様な部分でわずかに均等確率からずれてしまう。
ただし、ずれる範囲は、32767/100 = 327.67 なので、確率にして
0.67/327 程度以下の小さなずれではあるが。
>>246 剰余を取って特定範囲の乱数を生成することができるのは、元の乱数が MT 並に性質がよいときだけかと、つまり
>>246 はちみつ氏のやりかたは、元の乱数が優れたものだからできる方法
MT が発明されるまでは、最悪の方法「線形合同法」でもなんとか我慢できる部分範囲の乱酔生成法しか推奨されなかった
C FAQ をみてもそれがわかりますね
http://www.kouno.jp/home/c_faq/c13.html#16 13.16:
A:ある範囲の整数からなる乱数はどうやったら生成することができるか。
Q:すぐに思い付く、
rand() % N
(これは0からN-1までの数を返そうとする)は乱数の質が低い。なぜな ら乱数発生器の多くで下位のビットは悲惨なほどランダムでない。よりよい方法は以下のようなものである。
(int)((double)rand() / ((double)RAND_MAX + 1) * N)
>>252 乱数ソースの性質の悪い部分を分布関数で修正するのはレイヤの分離がきちんと出来ていない感じがして嫌だな。
下位ビットを捨てるなら捨てるでそれが明示的であるほうが好ましいと思う。
いずれにせよ
>>226 は、まともな標準ライブラリで試すと 226 のような結果に
はならないはず。理由:
226では、rand()%100の下一桁が常に9だが、それだとrand()は常に奇数という
ことになるが、実際のrand()は全て奇数ということはないから。
現象的には、偶数と奇数が交互に来るという不具合が知られていたりするが、
全部奇数ということはない。
超初心者スレであることを考えると
>>226 の srand() がプログラム起動時一度だけとも限らないのでは。
Windows の (msvcrt の) rand は線形合同法だが下位バイトを豪快に捨ててる。
そのせいか (下位バイトを捨てない線形合同法よりは) 乱数としての質は多少良いが
初期値の違いに鈍感で、初期値が似ていれば最初の乱数も近いということが起こる。
>>256 の指摘は妥当かもしれない。
>>256 つまり、rand()だけを繰り返しているのではなく、srand()とrand()の組を
ひっくるめて繰り返しているようなことなのかな。
なるほど、それなら問題の焦点はsrand()と時刻の関係性になるので
>>226のような結果になったとしてもおかしくはないな。
なるほど。
質問者は、だから>>227でも快い返事をしてくれなかったのか。
彼は例えば、以下の様に書いていたようだね:
(1)
for ( int i = 0; i < 20; i++ ) {
srand((unsigned)time(0UL));
int r=rand()%100-1;
printf( "r=%d, ", r );
}
本来は、こう書くか、
(2)
srand((unsigned)time(0UL));
for ( int i = 0; i < 20; i++ ) {
int r=rand()%100-1;
printf( "r=%d, ", r );
}
こう書く:
(3)
srand((unsigned)time(0UL));
for ( int i = 0; i < 20; i++ ) {
int r = (int) ( ((double)rand()) / ((double)RAND_MAX + 1.0)) * 100.0 );
printf( "r=%d, ", r );
}
この中で(1)はダメ。(2)も余り良くない。(3)はplain Cでの簡単な書き方では
標準。しかし、わずかに均等確率からはズれる。 >>255 >>226を見れば乱数になってないことは一目でわかると思うのだけど
>>255の時点で毎回srandを呼んでるのかとも思ったけど、
それにしても値が綺麗すぎる。
Cはよくわからんのだけど(3)のやつわざわざdoubleにキャストする必要あるの?
RAND_MAX + 1 でオーバーフローするとか
最低でも32767以上だからINT_MAXのときもあるのか…
ありがとうございます。
と思ったけどRAND_MAX+1.0した時点でdoubleになるんじゃ?
>>264 なるけど
書かなくても動作が同じであれば書かない主義?
カッコとかコメントとか
1.0 も 1. で良いんだよ
まあそれ以前に (3) はカッコの対応がおかしいな
>>253 確かに今となっては MT が開発されてしまったので、その感覚は理解できます
しかし、我々は MT がなかった頃の好き古き時代についても考慮するべきでしょう、過去の方法を評価するのに、その当時の技術的制約を考慮せずに「今の価値観」で裁断するのはフェアではない、と私はつくづく考えているのです
>>256-257 なるほど、従って
>>226 に対する適切なアドバイスは次のとおりだと私は提案します
>>226 MT = メルセンヌ・ツイスタを使いなさい
srand() とか rand() は忘れなさい、これらは化石時代の乱数生成法だから、今となっては srand() とか rand() をあえて使う合理的理由は存在しません
MT の導入方法や使い方は、次の私のソースを参考にしてください
https://ideone.com/M2SRcE http://2chb.net/r/tech/1434079972/60 どう見ても乱数生成法の質の問題じゃない
使い方が間違ってる
乱数の質を求めるならハードウェアの乱数生成命令を使うのが一番だが
>>226はそういうレベルじゃない
Visual Studioで以下をやったら
>>226みたいな値になった
3秒ごとにsrand/rand をコールしてるんでしょう
for (int i = 0; i < 100; i++) {
srand(i*3);
printf("%d\n", rand() % 100);
}
え?
>>226 って srand() を複数回呼んでいるんですか?確かにそれは間違っていますね…
srand() は普通、アプリ起動直後に一回だけ呼べば十分ですよ…
>>269 洞察すれば、こんな風だろうか?
(端末で確認しながら三秒間隔でEnterキーを押している) :
for ( int i = 0; i < 20; i++ ) {
srand((unsigned)time(0UL));
int r=rand()%100;
printf( "r=%d\n", r );
getche(); // 3 秒間隔で人間が Enter キーを押す。
}
>>269 洞察すれば、こんな風だろうか?
(端末で確認しながら三秒間隔でEnterキーを押している) :
for ( int i = 0; i < 20; i++ ) {
srand((unsigned)time(0UL));
int r=rand()%100;
printf( "r=%d\n", r );
getche(); // 3 秒間隔で人間が Enter キーを押す。
}
書籍の意味が分からないので教えてほしいのですが
それ以外のって部分から何を言ってるのか全く分かりません
”signed char a;である時は、aには−128〜127の数値しか入れられません。それ以外の数値を入れようとすると、普通は一番下の1バイト、つまり2進数での下8桁だけになり、上の方の桁は全て切り捨てられてしまいます。
最大値より大きい値になった時をオーバーフロー…略”
>>274 ロベールの107ページの
”signed char a;である時は、aには−128〜127の数値しか入れられません。それ以外の数値を入れようとすると、普通は一番下の1バイト、つまり2進数での下8桁だけになり、上の方の桁は全て切り捨てられてしまいます。”
↑この文が意味不明なので簡単に教えてほしいです
”signed char a;である時は、aには−128〜127の数値しか入れられません” ここまではなんとなく理解できたのですが…
>>275 そもそもビットとかバイトとかわかるの?
わからないなら、基本情報から勉強しないといけない。
>>276 この前のページに2進数 1ビット 1バイトなどの単位と各型のバイト数について触れられてるので
そこは何となく理解できてるのですが
>>277 1ビットは、2進数一桁で、ゼロかイチ。
2ビットは、2進数二桁で、00、01、10、11の2**2==4通り。これらは10進数で表すと0、1、2、3となる。
3ビットは、2進数3桁で、000、001、010、011、100、101、110、111の2**3==8通り。これらは10進数では、0、1、2、3、4、5、6、7となる。
……
8ビットは、2進数8桁で2**8==256通り。10進では0〜255となる。現代では8ビットは1バイトに相当する。1バイトは16進二桁で表せる(2**8==16**2)。
以上は符号なしの場合。
符号付きの場合は最上位ビットがマイナス符号の有無を表し、正の場合は符号なしと同じで、負の場合は2の補数表現になる。
2の補数表現というのがくせ者だが、まあ、Wikipediaの説明を見てもらいたい。
https://ja.m.wikipedia.org/wiki/2%E3%81%AE%E8%A3%9C%E6%95%B0 符号付き8ビットの場合はx+y==2**8となるyがxの2の補数となる。補数を使えば足し算で引き算を表せる。
まあ、例えば10進数4桁1234の10の補数表現は8766となる。1234+8766==10000となるが有効4桁からオーバーフロー(桁あふれ)してゼロになる。8767の場合は1234+8767==10001、
オーバーフローしてイチになる。このようにオーバーフローを前提とすれば、大きな数で引き算を表せる。
お、優しい先生が現れたぞ。嘘ばかりの5ちゃんの中で珍しい。
>>279 すいません詳しくありがとうございます
補数って概念全く理解してなかったので、それが原因だと分かりました。
コンピュータは足し算しかできないのですね…
そこら辺知識固めてからもう一度読み直してみようと思います。
10進4桁の場合、9999に1を足すと10000、オーバーフローしてゼロになる。よって、このオーバーフローするシステムの場合、9999はマイナスイチを表していると考えることができる。
同様に9998は-2であり、9997は-3である。
符号付き8ビットの場合、2進数11111111、つまり16進でFFがマイナスイチを表す。同様に11111110(FE)はマイナス2であり、11111101(FD)がマイナス3である。
規則性が分かると思うけど、ビットを反転して、符号なし整数と見なしてイチを足すとマイナス符号の追加と同じ効果がある。証明略。
一応補足しておくけど負の数の表現が二の補数であることは C/C++ の言語仕様としては保証してないし、
(C++20 からは二の補数であることが保証されるようになった)
1バイトが8ビットであることも保証してない。
signed char に型変換したときに上位ビットを切り捨てることも保証されない。
(変換後の型が unsigned のときには実質的に保証される。)
言語仕様として保証しないからといって間違っているというわけではなくて、
一般的なコンピュータのアーキテクチャではおおよそそうなってるのが普通というのも事実。
C++ の言語仕様の一部は機械の都合 (どのような機械語を生成するのが効率的か) でいくつかの選択肢
をとれるように言語仕様の側では意図的に決めてない部分がある。
「C++ の説明」として見たら
>>275 で引用されている説明はちょっと微妙かもしれん。
あまり踏み込んで説明するのがめんどいから「普通は」という言葉でごまかしているんだと思う。
char は環境依存なので使わないようにする。
unsigned・signed のどちらなのか、分からないため
unsigned char は、0〜256
signed char は、-128〜127
0〜127、7ビットの範囲では、この2つは共通している
signed charは、先頭ビットが1なら、負数となる。
2の補数を調べて
1111_1111・0xFF なら、256か、-1
>>286 修正
256 ではなく、255 です
unsigned char は、0〜255
1111_1111・0xFF なら、255か、-1
だから、環境依存のchar 型を使っていると、
エラーに、-1を使っていたが、他の環境では255と表示されたりする
むしろ int を期待してる引数に char 渡す時が危険
char 同士なら符号の有無が違ってもビットパターンは維持された
ままで型を読み替えることが期待できる (言語仕様として保証しているわけではない)
けど、大きな型に変換するときは符号拡張が起こることがあるからだね。
ハーバートシルト『STL標準講座』翔泳社, 1999, p.156-157
のサンプルプログラムで、そのままだとコンパイルが通らないものがあるのですが、
適当にconstをつけていたらコンパイルできるようになりました
しかし、理由がわかりません
どなたかご教示いただけませんか?
https://ideone.com/LGnjXo operator <<のとこでoがconst参照だから、そのoからはconstなメンバ関数しか呼べない。のでそれで合ってる
元のソースが間違ってるか何かだと思う、この仕様は最初からのはずなので
>>290 set<>::iterator は const をつけていなくても set<>::const_iterator と同じくイテレータ≒ポインタに const 属性がつきます。
だから set<>::iterator p; …@、と宣言した場合の p には「終生」 const 属性がつきまとうことになります。
例えば@の p にポインタ演算子 * を適用して出来た表現「*p」が参照に読み替えることがあれば、その参照は const 参照でなければなりません。
もともと const 属性はポインタにつけて、const 属性のついたポインタに -> 演算子を使って出来たメンバ変数の値を変更しないようにコンパイル時に厳密にチェックする縛りです
c++ における参照は「機械的にポインタを使った書き方に書き直すこと」が可能(…A※)ですから、const なイテレータ(≒ポインタ)から生成した参照は const な参照にならざるを得ないのです
※Aは私の持論で、今回のお題でも参照をポインタに全部書き換えてやろうと試行錯誤していましたが、さすがに iostream や set で先に参照として宣言されているものを後からポインタにするのは不可能でした
頑張ってみたけれども、かえって意味不明な
https://ideone.com/Yc0YvT ぐらいにしかならなかった、持論は修正しなくてはいけないなあ…
set は重複要素を許さない二分木構造です。二分木構造 set に要素を挿入するときに、要素の大小関係にしたがって二分木の形をくみ上げていきます。
だからすでに二分木に組み込まれてしまった要素が、後からほいほいと要素の内容を変えられてしまっては二分木構造に矛盾をきたし、役に立たなくなってしまう…
だから set にすでに組み込まれている要素をイテレータで走査するときは、そのイテレータ≒ポインタは、メンバの書き換えが不可能なイテレータとするしかないか、と私は考えます
提示していただいたソースを、上に述べた原則にしたがって、この原則に関係ない余分な部分を削り落として書く(あと、ちょっと簡略化もしています)と次のような感じでしょうか。
https://ideone.com/Zr1qIH friend 略 operator<<(略 C const &obj) { ... }
にならなくてはならないのは set<C>::iterator は set<C>::const_iterator と同じだからです
friend bool operator<(C const &a, C const &b) は set への要素の挿入のときに使う比較関数ですが、比較作業以外に要素のメンバを変えるとか余計なことをさせないために、最初から const 参照で宣言するべきでしょうし、そうなっているみたいですね
しかし、この const 属性はプログラミング 3 年生くらいまでは、かなり分かりにくい縛りであることは、私の経験からもとても理解できます。
ポインタや参照をしっかり理解しないことには、わざわざ自分を縛る const のありがたみもよく理解できないだろうと、私も同情するのです。そういうときは、const_iterator p から作った表現 *p が展開された先の実際の表現を、「*p のコピー・オブジェクトのコピー」にするのがいいでしょう
上記のお題をこの方針で書くとこうなります。
https://ideone.com/G42gUs いろいろ書きすぎたかもしれませんが、上に示した三つのソースコードを研究してみてください
>>290 >>292 http://2chb.net/r/tech/1594615908/593 593 名前:◆QZaw55cn4c [] 投稿日:2021/03/14(日) 20:13:24.03 ID:uaeFGveg [3/6]
>>590 >C++は未だ*や&、&&、で頭の中がグルグル回ってしまう
これらの「記号」は習得に順序があります。
まず * をしっかり理解します。C/C++ はなんといってもポインタが基本です。
次に参照 & を理解します。参照& を使う場面が出てきたら、これを * を使った書き方に書き直す、という機械的な訓練がいい練習になるでしょう
参照 で返す、という場面でも、@参照返しが出来る場合と、A参照返しはできずせいぜい RVO に期待するしかない場合、の@A二つの違いを明確に即答できるようになるべきでしょう(最近まで私はそれができなかった……)参照& の表現は新しい表現( ranged-for とか) でよく目にしますし、@Aは結構重要だと思います
&& は多分最後でしょうね、私も && は良く分かっておらず、というか、分からないから使わないという態度に留まっていますが、まあそれでもなんとかなる気がします
>>291 operator<<() のストリームじゃないほうの引数は、const 参照ではなくてもいいと思います
今回のは const 参照が要求されたのは、 set のイテレータだから
https://ideone.com/j6CV0s >>292 ソースを貼り付けた一行目がミスっていましたね、修正します。
>しかし、この const 属性はプログラミング 3 年生くらいまでは、かなり分かりにくい縛りであることは、私の経験からもとても理解できます。
>ポインタや参照をしっかり理解しないことには、わざわざ自分を縛る const のありがたみもよく理解できないだろうと、私も同情するのです。
>そういうときは、const_iterator p から作った表現 *p が展開された先の実際の表現を、「*p のコピー・オブジェクトのコピー」にするのがいいでしょう
>上記のお題をこの方針で書くとこうなります。
https://ideone.com/Ivx0JY ああ、operator <<のconstも最初付いてなかったのか
それならsetの仕様変更のせいだね
というか昔のままの非constの方が良かったんだけどなぁ
比較演算子自分で書いてるような構造体だと順序変わらない場合もあるんだし・・正直押し付けがましい
>>296 自分で一から書く分には const に一貫性を持たせて、結果、const が有用に働くように書いていけるかもしれない、とか思うのですが、
他の人の分を取り込むときは、最悪 const_cast を
>>290 の言うように「適当にconst_cast をつけていたらコンパイルできるようになりました」とか私も言っているわけでして、私は
>>290 を笑うことができません……
一から書いている私ですが、
全てのフォルダ・ファイル・プログラムに一貫して
*と何か名前を付けてプログラミングをしています。
QZ・・・・
C++をちゃんと理解できてないのに無理すんなw
>>299 >C++をちゃんと理解できてないのに無理すんなw
うん。すっごく認めます!
でもちゃんと理解できていないからこそ、アウトプットもきちんと書くようにして定着させたい、というのもあるんですよ
「教えることは教わること」
>>290 に対する回答としての
>>292,
>>294 に間違いはないですよね?
意味分からん理屈だな
ずっと前からC++分からないって言ってるよね?
もしかして理解できる頭を持ってないのかな?
>>301 自己申告なんて当てにしてはいけないのでは?
文面から必死な感じがヒシヒシと伝わってくるのに
皮肉も理解できないとはさすが厚顔無恥の代表格
誰も認めてくれないから自画自賛するしかないんですね
>>303 え?必死?思いがけない反応ですね
まあ
>>290 の方が提示したソースはハーバードシルトにしては冗長だと思って無駄丁寧っぽく説明したほうがいいかと
>>292 をワサワサ書きましたが、それが必死だとは…
よく分かっている方
>>291 に対しては簡潔に私の意見
>>294 を送ってもう十分、仕様変更があったという情報
>>296 をいただいて感謝、というところでしょうか
>>291 >>292 どうもありがとうございます
constメンバ関数の理解が不十分だったようです
constメンバ関数はメンバ変数を変更しないという理解だけで、
constオブジェクトはconstメンバ関数しか呼べないことへの
理解が足りなかっため私自身混乱していました
ご説明いただいた内容を足掛かりに理解を深めたいと思います
まぁ、いいじゃねぇか、プログラミングなんて何にも知らないってのスレだし。
const char* const str[] は文字列アドレスを格納するポインタの配列って意味であってますか?
const char* strは文字列を格納するポインタ?
char str[] は文字配列?
一気に出てきてよくわからなくなって来たので間違えてたら教えて欲しいです。
https://ideone.com/2fyV5M 103 と115で確保された動的配列のアドレスは別物なんでしょうか?
コピーコンストラクタの動きがよくわからないです
103のarrayはコピーされたものだから別物だよ
てか初っ端から手直しが必要なソースを貼るのはやめろ
スレの主旨的に初心者が初歩的な質問をするのは別に構わんとは思うんだが、
入門書にでも書いてあるようなことはよく読んで勉強したほうがいいと思うぞ。
素人が1レスで答えるよりはちゃんと体系だった解説のほうがわかりやすいよ、常識的に考えて。
>>312 すいません、ヘッダーとかcpp分けてるのどうアップロードすればいいのか分からなかったです
後65行目にcopy(other.m_array, other.m_array + m_size, m_array);とあるのですが何をしてるのか分かりません
本には”第1引数以上第2引数未満のアドレスにあるデータを第3引数の指すアドレス以降にコピーする関数で…とあるのですが
具体的に何をしてる関数なのでしょうか?第2引数の足し算も何なのかよく分かりません。
https://ideone.com/EScxwq こうしたらそのままコンパイル通るやろ
自分のヘッダincludeしてるとこにヘッダの内容貼り付けるだけ
https://cpprefjp.github.io/reference/algorithm/copy.html memcpyと似たようなもん(コピーの仕方は違うけど
other.m_arrayの指すアドレスから+m_size分のアドレスまで(未満)をm_arrayの指すアドレスから同じく+m_size未満までコピーしとるだけ
これで分からんならポインタの理解が出来てない
上記のとこだとイテレータとか出てるけどこの場合ポインタなので全部ポインタに読み替えていい
ちょっと誤解招きそうなので補足
m_sizeは個数なのでアドレス値ではないがintのm_size個分アドレスが加算される
このへんは
>>313の言う通り入門書嫁
cpp で socket を読み書きする stream 系の class ってありますか?
boost にはあったと思いますが
標準のはあるんですか?無いですか?
>>317 標準には無い。
が、ソケットに stream のインターフェイスをかぶせることはそれほど難しくはない。
>>315 1引数から2引数で足したアドレスまでを第三引数にコピーしてるのですね
やっと分かりました。ありがとうございます。
頭硬い人はロベール向いてないのかな…
>>318 thx
cpp の std にある関数で glibc の様な getpass ってありますか?
標準のは無いですか?
FILE *fp = fopen() で取得した fp を使って
stringstream としてアクセスすることは出来ますか?
>>323 直接的に一発で FILE* に stream をかぶせる手軽な方法はないと思うけど、
std::basic_streambuf を継承して setbuf, overflow, sync などをオーバーライドしたクラスを作ればストリームバッファになる。
(普通は std::basic_filebuf も内部的にはそう実装されているはず。)
それをストリームに結び付ければストリームに出来ることは何でもできるよ。
仕様を調べるのがすごくしんどいだろうけど、
実装は (細かいエラーチェックとかを抜きにすれば) 百行も要らないくらいの簡単なものでいけるんじゃないかな。
>>323 fstreamを使えば?
#include <fstream>
#include <sstream>
…
std::ifstream fs("hoge.txt");
std::stringstream ss;
ss << fs.rdbuf();
fs.close();
それともfstream使えない特殊な環境?
FILE *fp = fopen(...);
std::ifstream fs(fp);
出来たらいいな
関数へ渡す引数の型を限定したいときどう書くのが一般的ですか?
具体的に言うと符号なしのintだけ受けつけたいんですけど
>>327 暗黙の型変換を許さないということかな?
それならテンプレートにした上で型に制約を付ければいい。
ここでは C++11 でも通るように書いてみたけど C++20 以降なら
コンセプトが使えるのでもう少し簡単に書ける。
#include <type_traits>
template<class T>
typename std::enable_if<std::is_same<T, unsigned int>::value>::type foo(T) {
}
int main(void) {
int a = 1;
unsigned int b = 2;
foo(a); // これはエラーになる
foo(b); // これは通る
}
確かにそれで可能だけど、回答が超初心者スレのレベルを逸脱していると思うのですが
>>329 単なるサンプルだからだよ。
>>330 超初心者が相談するという主旨のスレではあるけど、
超初心者には理解できないという結果になることもあるだろうし、
可能であれば相談した結果として初心者から脱したらそれに越したことは無いでしょ。
これで相談がクローズってわけでもないから
もっと深く知りたいってのならわからないところを続けて質問してもらってもいいわけで。
もっと簡単な方法があるならそれを提示するんだけども、なくなくなくない?
>>331 アホか
普通のenable_ifの使い方と全く違うお前だけのオナニーコード押し付けて何がサンプルだ
何不必要な制限勝手につけてドヤってんだボケ
>>332 返却値 (または enabler) で制限するのは普通だろ。
むしろ他にどう使えるんだ?
>>333
マジで言ってんのか?
#include <type_traits>
template <class T, typename std::enable_if<std::is_same<T, unsigned int>::value>::type* = nullptr>
void foo(T)
{
}
int main()
{
// foo((int)1);
foo((unsigned int)1);
}
enablerってこれのことか知らんが、お前のコードだと戻り値voidにしか出来んだろってこと >>327
ちなコンセプト版(C++20対応コンパイラが必要)
#include <type_traits>
template <class T>
concept UnsignedInt = std::is_same_v<T, unsigned int>;
template <UnsignedInt T>
void foo(T value)
{
}
int main()
{
// foo((int)1);
foo((unsigned int)1);
}
(インデントは全角なので注意)
まぁどっちも難しいと思うけど無理に理解せず流した方がいいと思う(それか制限あきらめるか >>331 いや、お前の言いたいことは分かるよ
ただテンプレートメタプロコードを超初心者にいきなり例示して、「わからないところを続けて質問」して回答を繰り返して、結果的に理解に至るのは何ヵ月後になるんですかと
テンプレートに関する高度な質問が飛び交う中、ここは超初心者スレとして機能するんですかと
この場合
>>327が求めているのはドリルじゃなくて穴だと思うよ俺は
どういう背景があってunsigned int以外を受け付けたくないか、を聞くべきなのでは?
確かにそうだね
というか自分もテンプレート以外思いつかんかった・・
>>333 なんか変な癖あるから標準的な使い方がすっぽ抜けてたのかね
ボロカス言って悪かった
あんまり詳しくない俺にはこういうのしか思いつかん。
__my_func() は直接呼ばないお約束にしておいて、static_assert で。
template のところは、書き換えは雰囲気でできると思うけど・・・
#include <type_traits>
#include <iostream>
unsigned int __my_func(unsigned int a) { return a * 2; }
template <class T> unsigned int my_func (T a) {
static_assert(std::is_same<T, unsigned int>::value == true, "is not uint.");
return __my_func(a);
}
int main() {
int a = 2;
unsigned int b = 2;
//std::cout << my_func(1) << std::endl; // assert
//std::cout << my_func(a) << std::endl; // assert
std::cout << my_func(1U) << std::endl;
std::cout << my_func(b) << std::endl;
}
>>334 > お前のコードだと戻り値voidにしか出来んだろ
なんか変なこといってると思ったらそこがすれ違いか。
std::enable_if のテンプレート引数の二個目を省略しなければ何にでも出来るよ。
(std::enable_if の type は void に固定されているわけではない。)
クラスやコンストラクタは返却値がないから enabler を使うんであって、
普通の関数のときは返却値のほうで制御するのが普通だと思うぞ。
>>336 まあそうなったら他に誘導してもいいし、資料を提示するだけで十分だと思った。
ただ背景をもうちょっと引き出すべきというのも確かに必要なことではあったな。
そうなんか、そういえばいつも自作alias使ってたから気付かんかったわ
>普通の関数のときは返却値のほうで制御するのが普通
別に戻り値でも引数でもいいが、クッソ読みづらいと思うけどな
あとそれならこういうスレで第2引数省略すんなよ、初心者惑わしたいのか?
ここは中級者が、お互いを煽り合うスレでは無い、ということを理解して欲しい。
>>342 俺ははちみつが書くより先に同じこと(enable_if)思ってたけど、このスレには不適切だと思って書くのやめてたんだけどな
あんな不適切で不親切な回答(テンプレートとSFINAEとか、はちみつも使いこなせてないようなものを使う上に戻り値の変更方法も、自身が言ってるコンセプト版も書かない)に怒っちゃいかんのか
>>344 そこらへんが少しばかり詳細なら初心者に理解できる内容になるという主張?
少々の書き方の工夫で初心者がわかるように解説できるわけないだろ。
関連知識も含めればちょっとした本一冊分くらいにはなる内容なんだから。
「まずはテンプレートの知識が必要ですね」ということが初心者に対する解で、
そこに至る前にごちゃごちゃしたことを詰め込むのは不親切だと思うわ。
>>343 戻り値だけ違う同名関数は作れないのでテンプレートにするか、引数で戻り値を指定するしかないとおも
template <typename T>
T hoge();
template <>
int hoge<int>() {}
template <>
float hoge<float>() {}
hoge<int>();
hoge<float>();
もしくは
int hoge(int) {}
float hoge(float) {}
?hoge(int());
hoge(float());
https://pastebin.pl/view/e395f5ca operator関数の動きがよくわからないんですが
tmp.x = x + p.x;
これの p.xと xとtempはどのオブジェクトのことを指してるんでしょうか?
>>348 operator+ は演算子 + の実体として機能する。
故に p1+p2 は p1.operator+(p2) と書いた場合と完全に同じ。
tmp はもちろんこの関数内で宣言した tmp 変数だし、
p は渡された引数 (この場合は p2) のコピーなので p.x には 6 が入ってるね。
>>349 ありがとうございます。引数がどれに対応してるかわかりました。
p1.operator+(p2) これは何でしょう?
掛け算の*と、
色々を示す*が
同じ*なんで困っていますが、どうしたらいいんでしょうか?
色々ってワイルドカードのこと?
C++においては*は乗算かポインタ関係だけだよ
>>350 p1のメンバ関数として普通にoperator +を呼んでるだけ
ありがとうございます。
c++ のワイルドカード記号ってなんでしょうか?
言語そのものには無いよー
エディタやIDEで検索するのには使えることもあるが
教えてもらって、勉強になりました。
ありがとうございました。
https://pastebin.pl/view/31e451ad クラスの型変換と型変換用のコンストラクタの意味が全く分からないのですが
これをすると何が得なのでしょうか?10行目は普通のコンストラクタに見えますがなぜ変換用?
入門書に載ってるコードなのですがエラーで動作もせず何がなんだか分かりません…
2つ目のprivateはpublicの間違いじゃね?
あと変換は、単に引数一つだけを受け取るコンストラクタは
自動的に?暗黙のキャストにも使われる、というだけ(それを禁止する方法もあるが
>>357 おかげさまで動きました。ありがとうございます。
でもいまいち型変換の意味が分からないのですが
operator 型名()return 変数を定義するとどの変数にも代入出来るようになるってことですか?
C++ キャスト でぐぐるといいよ
(キャストはCにもあるけど)
>>358 型変換はその名前の通り型を変換する。 変換と同等の処理を普通の関数とし
て書いてもかまわないんだが、変換関数 (conversion function) または変換
コンストラクタ (converting constructor) が定義されていると暗黙の型変換
が適用される文脈では勝手に適用して変換してくれるので便利。
例えば以下のように foo 型のオブジェクトを受けとる文脈で bar 型のオブジェ
クトを渡しても通るのは変換が適用されるから。
struct foo {};
struct bar {
operator foo() {
return foo();
}
};
void func(foo) {}
int main(void) {
foo x = bar();
func(bar());
}
>>360 ようやくイメージできてきました。ありがとうございます!
>>360 そんな難しくせずに、
{ change A to B }
でいいんじゃないの?
コマンドライン引数の意味が全く分からないのですが
Visualstudioを使っているからでしょうか?
それとも、コマンドプロンプトの使い方を理解できないでしょうか?
https://programming.pc-note.net/c/commandline.html ここも参照にしたのですが何が得で何ができてるのかよく分かりません。
コマンドラインってVSでデバッグ無しで実行をした時に出る黒い画面ではないですよね?
質問ばかりですいませんが本当に何も分からないのでお願いします。
>>364 メモ帳でファイルをドラッグアンドドロップで開く例が紹介されているが
これはWindowsのShellであるExplorerがexefileに対して登録されているドラッグアンドドロップハンドラーを処理してドロップしたファイルのフルパスを文字列として起動するプロセス環境のコマンドラインパラメータとして渡している
黒い画面(コマンドプロンプト)にもExplorerとは違うがプロセスの起動とパラメータを渡す機能が実装されている
起動するexefileに続けてスペースを開けたあと記入した文字列がそのままパラメータとして渡される
ファイル名以外にも自由に渡せるためプログラムの動作を指定したり変更する目的で使用される
あなたが作成するプログラムでシェルから渡されたコマンドラインパラメータを確認する方法はそのページにもある通りだ
コマンドラインパラメータを活用してバラ色の人生を満喫してくれ
例えば、デスクトップにショートカットを作る。
コマンドプロンプトを起動して、Ruby スクリプト・a.rb を実行する
リンク先
C:\Windows\System32\cmd@.exe /k "ruby C:/Users/Owner/Documents/a.rb"
注意。書き込めないので、間に@を入れました
作業フォルダ
C:\Users\Owner\Desktop
a.rb 内には、puts ARGV
(ARGV は配列で、そこにコマンドライン引数が渡ってくる)
と書いておいて、ショートカットに、フォルダx・ファイルb.txt をdrag&drop すると、
コマンドプロンプトが起動して、以下のように表示される
C:\Users\Owner\Desktop\x
C:\Users\Owner\Desktop\b.txt
const char* const str[]={"aaa","bbb","ccc"}
constの効果を教えてほしいです
後ろのstrの前のconstは付けると
const str[0]="dddd"って出来なくなるのは分かったのですが
先頭のconstが分かりません
ロベールC++入門の代入演算子についてなのですが
コピーコンストラクタのときは動的配列をdelete[]しなかったのに
なぜ代入演算子を使うときだけdelete[]するのか分からないので教えて下さい
本にはm_arrayには前に確保したメモリが存在するためdelete[]しないとメモリリーク
と書いてあるのですがコピーコンストラクタも同じじゃないの?と混乱してます
100行目です
https://ideone.com/xL8UOn newしたメモリが不要になったらdeleteする
これだけ
コピーコンストラクタでのdelete、
いつnewしたデータに対して?
>>372 すいません、わからないです。
コピーコンストラクタはnewでアドレスを確保しないものなのですか?
>>373 ロベールの C++ 入門を読んだことがないからどういう構成になっとるか知らんけど、
それがわからんのならたぶんそれ以前の章を理解でてきないと思う。
>>371 代入演算子は既にあるオブジェクトを別のオブジェクトで上書きする操作
コピーコンストラクタは別のオブジェクトから新しいオブジェクトを作って初期化する操作
代入演算子でdelete[]しているのは既にあるオブジェクト(*this)のメンバとして確保済みのメモリ領域
コピーコンストラクタの実行時には「既にあるオブジェクト」にあたるものは無いので、deleteするものも無い
>>375 初期化と代入の知識が曖昧でした
分かった気がします。ありがとうございます。
AtCoderの初心者向けのC++の説明のページを読んでいます。
vector<int> a(10);
aの第i番目の要素にアクセスする場合、a[i]よりもa.at(i)と書くほうが良いと書いてあります。
これは現在のC++で推奨されている書き方でしょうか?それとも単に初心者はそう書いたほうがいいというだけのことでしょうか?
>>377 >a[i]よりもa.at(i)と書くほうが良い
そう主張されている理由はどのように書かれていますか?私はどちらでも大差ないと思っていますが‥‥
>>378 vector<int> a(10);
b = a.at(10);
などと書いた場合にコンパイルエラーになりますが、エラーメッセージがatを使うと表示されるというのが理由です。
初心者でないプログラマーでatを使って書いている人は少数派ではないのですか?
範囲外にアクセスする可能性があるならat、ちゃんと事前にチェックするなら[]でいいんじゃない?
vector配列を指すポインタを使ってる時に[i]で指定する書き方がよく分からないのでat(i)使ってる
>>377 これのことだね。
https://atcoder.jp/contests/apg4b/tasks/APG4b_n 例外処理やアサートの説明を省略しているせいでどう使い分けるべきものなのかがよくわからん説明になってる。
C++ はかなり複雑で、 AtCoder のサイトにある雑な説明だけでは細かいところまで理解はできないよ。
C++ の言語仕様の詳細を理解するのに手間取って競技を始められないくらいならそういう風に割り切れという意味で
AtCoder としては at を推してるんであって、言語仕様やプログラマの習慣としてどちらかを推奨してたりはしない。
それぞれに用途がある。
余談だが C++ の言語仕様としては推奨というのはないが非推奨というのはあって
(結果的に同等のよりよい機能を推奨するのと同じことになっている場合はある)
将来の言語仕様の更新で廃止するつもりがあるということを意味する。
Notepad++でcppファイルを選んで実行をすると
Visualstudioが立ち上がるのですが
どうすればNotepadで実行出来るのでしょうか?
>>388 コンパネ→既定のプログラム→ファイルの関連付け
か
設定→アプリ→既定のアプリ→ファイルの種類ごとに
あたりでなんとかならないでしょうか?
>>389 回答ありがとうございます。
ファイルの関連付けをメモ帳とVisualstudioしか選べなかったです。(後Microsoftストア)
Notepad++は初期設定結構大変な感じなんでしょうか?
https://imgur.com/a/V3jOiV0 >>390 たしかに「設定→アプリ→既定のアプリ→ファイルの種類ごとに」
はうまくいかないですね
では、
開きたい拡張子を持ったファイルを右クリック→プログラムから開く→別のプログラムを開く→その他のアプリ→このPCで別のアプリを探す
ではどうですか?
私は win7 メインで、うまいアドバイスができなくてすみません‥‥
C++でアプリを作る場合って、QTってやつかMFCって奴を勉強すればいいのでしょうか?
C++でWIN32APIを学ぶっていうのはないですか?
メッセージループによるイベントドリブン型アプリケーション
「ウインドウ」と「メッセージ」というウインドウズの基本概念ぐらいは理解してもいい
tcl/tk
wxWidgets
DXLib
Unity
>>392 「C++でwin32api」ですか…
そういうのは c で win32api を理解した後、各自が独力で工夫して c++ と win32api とを辻褄あわせするものだと思っていましたが、それはそうと、そういう書籍は過去にありました
たしか leaf というライブラリと WOOL という lisp 処理系が掲載されていた記憶があります
MFC は何十年も前だけど、今もあるの?
QT は、Linux で聞くけど、Windows で使うの?
>>398 Qt5Core.dllで検索する色々出てくるから、win/macとマルチのアプリなんかで割と使われてみたいね。
手元だとfusion360とかresolveとかで使われてるっぽい。商用ライセンスあるからかな?
>>392 MFC は API の利用をちょっと楽にする薄いラッパーという感じだな。
API のことを忘れて MFC の使い方だけ学べばよいというようなものではない。
>>397 今は C++/WinRT の時代だぞ。
>>397-401 WIN32やったことないんですが
C++でアプリを作るときはWin32APIは避けては通れないのですか
ありがとうございます…
>>402 いや自分で書いてるQtって奴や>396なら違う世界観を満喫できると思う。
2Dゲーム系ならSDL2あたりも。他にもメンテされてるライブラリあるけどSDL2で引けば出て来ると思う。
>>401 ええ?
WinRT って .NET の世界のものかとおもっていました
>>405 WinRT は Windows のモダンな API セットで、特定の言語に結びついたものではない。
無名クラスのメンバ関数の実装を宣言と別にすることって可能ですか
struct {
int func_hoge(int n);
} myClass;
(実装)?
std::vecotrのインスタンスを作ったとき、指定した要素数以上のメモリを確保しないようにはできますか??
普通でなく指定したバイト数以上のメモリを確保しようとしたら例外が上がる実装例
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
#define MAX_SIZE 100
template <class T, class Alloc=allocator<T>>
class SizeLimitedAllocator {
public:
typedef T value_type;
T *allocate(size_t n) {
if (n > MAX_SIZE) throw bad_alloc();
return allocator_traits<Alloc>::allocate(allocator_, n);
}
void deallocate(T *p, size_t n) {
allocator_traits<Alloc>::deallocate(allocator_, p, n);
}
private:
Alloc allocator_;
};
int main()
{
vector<char,SizeLimitedAllocator<char>> vec(MAX_SIZE);
try { vec.resize(MAX_SIZE+1); }
catch (bad_alloc& e) { cerr << e.what() << endl; }
return 0;
}
void *q = (void*)p;
void *r = reinterpert_cast<void *>(p);
void *s = static_cast<void *>(p);
どっちが良い?
>>412 static_cast で可能なものなら static_cast を使うのが行儀が良い。
Cスタイルのキャスト記法は適用範囲が広すぎて意図通りではない (危険な) 変換でもコンパイルが通るかもしれんということで
複数のキャストを用意しているので意図にあてまる限りなるべく狭い効果を持つキャストを用いるべき。
githubからcshogiというパッケージをインストールしようとしたところ
ビルド中に
src/mate.cpp:110:26: error: template parameter redefines default argument
というエラーが発生しました。
実行コマンドは
CPPFLAGS=-std=c++17 pip install git+
https://github.com/TadaoYamaoka/cshogi としているのですが、あれこれ調べてもう打つ手がなくなりそうです。なにが悪いでしょうか。
macOS12.2付属のclangでビルドしています。(他の人は使っているので、文法などは問題ないはずだと思っています。)
Borland C++Builder 1が無料ダウンロードできるようですが
Borland C++ Compiler 5.5 freeとは全く別物でしょうか?
1は大昔のを記念に無料DL可にしたやつじゃないかな
最新のやつもCommunity Editionていう無料版があるから、開発に使うならそっち
あとBuilderはVisual Studioのような統合開発環境でコンパイラも含まれる
ロベール読んでるけど、途中からコードとファイルを端折りすぎてどこに書いてるのか理解出来ない
>>420 その本(サイト?)はあまり読んでないからわからないけど、こういう知識・技術系は複数の本やサイトを利用したほうがいいかも
基本はそのロベールで、曖昧な部分は他のテキストでみたいに
まあ逆でもいいけど
分割コンパイルの仕組みちゃんと理解しないまま雰囲気でヘッダインクルードしてるんですけど
cppファイルに#pragma once書かないのってどうしてですか??
>>422 まあ普通一回使ったら足りるからだけど、
cppをincludeしてたら意味があるのかもな
cppってインクルード出来たんだ
ヘッダーだけかと思った
単にコピペしてくるだけだけだからなんでもいいぞ
ルックアップテーブル計算してテキストにダンプし、ソース中に#include "table.txt" で取り込むのを見たことがある
IDEだと、プロジェクトに.cppを含めるとコンパイル対象になるので.inlとかにしておくのが無難
前は中身がcppっぽいのはcppにしてたけど
インクルード前提のファイルはhにするようにした
#define ほにゃらら
#include ファイル名.h
##undef ほにゃらら
インクルードしても単体ソースとしても使えるヤツはcpp
ツールが吐き出したコードやデータでそのままincludeして使えるものは拡張子はそのまま
h と hpp どっちにするかの話じゃなくて
(h or hpp) にするか
(c or cpp) にするか
の話
初心者はトリッキーな使い方はしない方が良いから聞かなかった事にして
なんか、すごい達者さんが並んでますけど、
ここって、
「プログラミング初めたいけど、なんにもわからないので、初めから教えてください。」
というスレです。
最初からでも0からでも構わんが
自分で努力しないやつはだめ
掛け算の*と、「何ですか?」の*と一緒なんですが、
区別する方法を教えてください。
>>439 掛け算の*は二項演算子
「何ですか?」の*は単項演算子
*の前に項があるかどうかで判断する
数字の、xxxと、
数字の、AAAの掛け算は、
xxx*AAAで、いつも迷うんです・・・
map よりも unordered_map の方が高速ですか?
あと追加順が保障されないのが unordered_map ですか?
map は何順ですか?
>>448 > map よりも unordered_map の方が高速ですか?
操作によるので一概には言えない。
一般的には unordered_map のほうが有利なことが多いとは言えるけれど。
> 追加順が保障されないのが unordered_map ですか?
map でも unordered_map でも追加した順序は保持されない。
C++ に限らず辞書的なデータ構造では格納順序を保持しないのが普通で、
保証があるのは Ruby の Hash くらいだと思う。
Go や Rust だと辿る順序を乱数でかき乱す実装になっているくらいだし。
> map は何順ですか?
キーの順序。
特に指示しなければデフォルトではキーを std::less で比較した順序。
そもそもmapの順序ってなんぞや
そりゃ内部表現としての順序(あるいは非順序という名の実装依存の順序)はあるけど
腹ワタ開腹して弄くり回したら、それはもうmapとは呼べねーよ
vector<int*> xの特定の要素を削除したい場合
delete x[1];
してから
x.erase(x.begin()+1);
という手順であってますか?
deleteしないとメモリリークしますよね?
>>452 それでいいよ。
でもスマートポインタを活用するとかの工夫はしたほうがいいね。
bitset<4>("1101")をsigned longに変換したいのですが
簡単な方法は無いでしょうか?
to_ulong()はあるのですが、to_long()が無いっぽいです
unsigned longからlongにキャストすればいいだけでは?
念のため補足すると、変換後の整数型が符号付きである場合にその型で表現できる範囲をからはずれたときの結果は定義されていない。
しかし bitset<4> を元にするという前提の元では signed long int の範囲からはずれるということはありえない
ので signed long int にキャストするという対処で正しい。
すみません肝心なことを書き忘れていました
2の補数表現された2進数の文字列を
signed longに変換したかったのでした
文字列は諦めて、
-(signed long)bitset<4>(~0b1101+1).to_ulong()
だと一応期待した動作なのですがなんか野暮ったい…
4ビットだから符号無しなら0~15だろ
コレを-8~7の符号付きにしたいということか?
誘導されて来ますた、
質問なのですがstd::stringに格納された数値文字列を数値にしたい、
しかし数値以外の文字(ただし空白文字は認める)が後ろにくっついていたらエラーにしたい、と言う場合どうす
れば良いの?
ダチャい書き方ならできうるけど人類はいつまでstrtod()や&(str[0])……
>>462 strtod で何が不満なの。
空白かどうかで区別が必要なら空白かどうか確認するしかしょうがないし、
ダサいもくそもないだろ。
>>463 だって&(str[0])とかナマポやし……
文字列型がchar以外になったら(std::basic_string<TCHAR>とか)になることも見越したら
手でテンプレート書かないといけないから牛刀感があるし、
文字列が厳格に数値文字列なのか検査するとかアプリのコードであるあるなので
アプリレベル(高級アセンブラ的でない書き方)の手段が用意されていて然るべきな気がして仕方が無いし、
無いというなら仕方が無いが、漏れはちょう初心者ですら……
>>464 std::stod は std::string と std::wstring に対応してるよ。
>>466 std::stod()は数値への変換が行われなかったとき例外をスローするが
後ろに余計なものが付いていたらスルーするんじゃ……
なお試したことはありま栓、
>>467 ???
それで何か困ることがあるという話なの?
要件が不明瞭でよくわからん。
実は正規表現でも使えば何とかなる……
のか……
std::regex re("^\s*([\d.]+)\s*$");
std::smatch m;
if (std::regex_match(str, m, re)) {
return m[1].str().strtod();
} else {
エラー
}
>>468 仕様は最初に提示stkr、
123.456E+8 : OK
123.456E+8a : NG
>>470 続くものが何であるかは自分で確認してエラーにするという話をしてると思ったんやが。
>>471 >続くものが何であるかは自分で確認してエラーにする
・できればライブラリでやってホスイ
・自分で書くとしてもナマポ(&(str[0]))は避けたい(
>>464 ・std::string部分が他の文字列型に変わっても大丈夫なサポートがあるならそれに乗っかりたい手でテンプレートを書きたくない(
>>464 できるかできないかで言えば、std::stringについてはダチャくあっても実現できてはいるので
C++でちょう簡潔に書ける手段が実はあるのではないか、ありませんか、というのが質問の意図
>>472 続くものの種類で判断するというピンポイントな要求にマッチするものはさすがに標準にあるわけない。
それを除けば std::stod が十分に要求を満たしているように見える。
単位でも確認したいの?
だったらstd::ends_withとかstd::rfindとstd::substrで数字の後ろ切り出すとかでチェックしてからstd::stodでよくね
チェックは自分の要件だから自分で書け標準ライブラリはお前のお母さんではない
>>474 > 単位でも確認したいの?
> だったらstd::ends_withとかstd::rfindとstd::substrで数字の後ろ切り出すとかでチェックしてからstd::stodでよくね
std::stringに格納された数値文字列を数値にしたい、
しかし数値以外の文字(ただし空白文字は認める)が後ろにくっついていたらエラーにしたい(
>>462 > チェックは自分の要件だから自分で書け標準ライブラリはお前のお母さんではない
チェックのためには(例えばstd::stodが)どこまで読んだのかの情報が要る
std::stodの裏側では文字列を数値解釈する枯れたコードが動いているわけで、
そいつにどこまで読んだのか、ただ1個の整数データを聞けさえすれば良い。
これはそれほど無茶な話ではないはずで実際strtod()ではできるから
どっちかというtライブラリにちょっち不備があるのでは案件であってお母さん案件ではない。
>>475 上に書いた通り(例えば)std::stodがどこまで読んだのかだけイブラリが返してくれさえしたら解決するのじゃ
正規表現は意味的には合目的的な手段やが、普通の正規表現エンジンの実装なら正規表現オブジェクトを作った際に
FSMを(表形式か何かで)生成する処理が中で動くので、そんなに軽い処理ではないからやっぱ牛刀感みある…
いったん作ったらマッチングは表駆動でやれるので速いことが気体できるのではないか、という香具師が居るかもしれないが、
実はstd::stod()に最大限仕事させたい(正規表現の側で数値文字列の書式についてわざわざ指定したっくない
場合は
>>496の正規表現は正しくは "^\\s*(.*?)\s*$"にせねばならないからマッチング時にバックトラックが発生して遅い可能性がある
これもちょっちイヤソな理由
繰り返しになるが(例えば)std::stodがどこまで読んだのかだけイブラリが返してくれさえしたらこんな考慮は不要で完全に円満に解決するのじゃ……
>>476 そんな長文ギャンギャン書きなぐってる暇があればstodの仕様くらい調べろよ
ちゃんとお前の欲しがってる物を返してくれるよ
便乗質問していいですか
某所で似たような問題があったのだけど、付加条件として、数値がINT_MAXを超える場合は
INT_MAX、INT_MINを下回る場合はINT_MINを返す、がありました
stodを使う場合(stoll等でもいいですが)、これってどうやって処理すればいいですかね
念の為「数値が」というのは元の文字列での、です。たとえば "1000000000000"みたいな
可能性としてはLONG_LONG_MAXを超えている場合もありますね
stoi系は範囲越えたらstd::out_of_rangeを投げるはずだが
_MAXで超えたか_MINで超えたかってわかりますかね
>>484 https://ja.cppreference.com/w/cpp/string/basic_string/stof > pos がヌルポインタでなければ、ポインタ ptr (変換関数の内部的な変数) が str.c_str() 内の最初の変換されなかった文字のアドレスを受け取り、その文字のインデックスが計算されて *pos に格納されます。 これは変換によって処理された文字数になります。
> 引数
> str - 変換する文字列
> pos - 処理された文字数を格納する整数のアドレス
>>483 そうですね、でも文字列の先頭とは限らないですよね。やはりこの場合はある程度は
自力で文字列をパースする必要がある感じですかね
ちなみに数字以外が含まれるときの挙動は "hoge 123"みたいに数字より前に非数字
がくるのは駄目だけど逆に"123 hoge"みたいのはおkなんですね
話題がないから質問してみる
struct Summer {};
Summer summer;
Summer *const summerConstPtr{};
const_cast<Summer*>(summerConstPtr) = &summer; // だめ
const_cast<Summer*&>(summerConstPtr) = &summer; // いける
質問1) 最後のいけるやつのconst_cast<Summer*&>の「&」はどういう意味なんでしょう? 参照のことかいな?
質問2) なんでconst_cast<Summer*>ではだめなのかな?
なんか変換されたw
∑merでなくて&summerです
>>488 参照が絡むとややこしくて単純に説明できないんだけど
代入演算子の左側は変更可能な lvalue (modifiable lvalue) であることということになっていて
そのキャストだと prvalue になってしまうから代入できないという結果になる。
たとえば
int x = 1;
x = 2;
は有りだけど
1 = 2;
は駄目なのはわかるでしょ。
この代入のときの x はそこに入っている 1 という値に意味はなくて場所に意味がある。
値として取り出されてしまうと代入できないんだ。
どういうときにどういう値カテゴリに属すことになるのか正確なところはここ見て。
https://timsong-cpp.github.io/cppwp/n3337/basic.lval C++03 時代は lvalue と rvalue だけの単純な (と言ってもそれなりに複雑だが……) 世界だったんだけど
右辺値参照の概念を整理するため (?) かだいぶんごちゃついてる。
>>490 返答ありがとう。
なぜconst_cast<Summer*>(summerConstPtr)が左辺としていけないのかがわかりませぬ。
summerConstPtrはconst_cast<Summer*>によって「Summer *const」から「const」が外れて「Summer*」となって
Summer *summerPtr;
summerPtr = &summer;
とするときの左辺summerPtrと同じようになったわけではないのでしょうか?
どうもこの左辺summerPtrと同じようにするためには、const_cast<Summer*&>としなければならないようだが、この「&」にはどんな意味ががが??
>>492 型とは別に (型と無関係ではないが) 文脈にカテゴリが存在するというのが肝心な部分。
どれがどのカテゴリに属すのかはダラダラとした箇条書きで書いてあって単純な原則では示せない。
(結果的には辻褄の合うようになってるけど……。)
& は参照を表す記号という解釈は正しい。
参照は lvalue なのでキャストの結果も lvalue ってだけ。
>>492 その理解だと↓も通ることになると思うんだけど、これが通らない理由もわからない?
int i = 0;
static_cast<int>(i) = 1;
>>493,494
「&」はやはり参照でしたか。
左辺の規則と右辺の規則があり、キャストしたポインターでは左辺の規則に従ってなくて、キャストした参照なら左辺の規則に従っていると、そうなっていると覚えるほかないのでありますな。
ありがとう。
c++に限定される疑問ではないかも知れませんが標準出力がどうやってコンソールに出力しているか?というところで躓いてます
gnuのlibcを見てもわからず、アセンブラを見て0x80というシステムコールをしているところまで辿り着いたけど無学なので理解できずにいます
OSが用意している機能を実行しているという認識であってますか?
>>499 そうだよ。
現代の OS は権限の管理がしっかりしてて、アプリケーションは
プロセスの外のリソース (メモリやデバイス) を直接には使えない。
OS に要求して適当なところに橋渡ししてもらう構造。
>>500 どうやって実行中のコンソールに出力しているのだろうという素朴な疑問だったのですが、この先はOS仕事という事なんですね
自分で見ろって言われるかもしれませんが、OSの処理の実装を見るのは難易度高いですか?
HelloWorldからどちらに進もうか迷ってます
同様のテーマのITmediaの記事を見つけたので腰を据えて取り組んでみようと思います
回答いただきありがとうございましたお騒がせしました
>>501 標準出力の実態はパイプ。
パイプの接続先がターミナルのプロセスが繋がってるだけでカーネルはそれほど大したことはやってない。
と言えれば簡単なんだけど端末制御まわりは歴史的事情でよくわからんことになってるので
ソースコードだけから読み取ろうとするのはしんどいと思う。
shared_ptrの解放時にweak_ptrを登録していたSTLコンテナから登録抹消したいけど、
shared_ptrのデリータでshared_ptr自身は扱えないっぽい。
出来ないということは、何か他にいい方法があるか、根本的に何か考え方間違ってる?
>>504 設計意図次第だけど
コンテナにはオブジェクト本体をいれて shared_ptr は
コンテナ内の要素を指すイテレータを指す
という構造はどうだろう。
#include <iostream>
#include <memory>
#include <set>
int main(void) {
std::set<int> container;
auto [iter, result] = container.emplace(42);
{
// コンテナ内の要素を指す shared_ptr をいくつも作る
auto x = std::shared_ptr<decltype(iter)>(new decltype(container)::iterator(iter), [&container](decltype(container)::iterator* p) { container.erase(*p); delete p;});
auto y = x;
auto z = x;
// コンテナの中には要素が入ってる
for (auto& x : container) std::cout << x << " ";
std::cout << std::endl;
// shared_ptr はここで消滅
}
// デリータが消したのでもう残ってない
for (auto& x : container) std::cout << x << std::endl;
}
>>505 ありがとうございます。実体とイテレータ、参考になります。
おかげで解放時何とかshared_ptrで引数を渡そうとしてましたが、諦めて実体でもいいんではと思い始めました。
回答を見るまでは、shared_ptr<shared_ptr<X>>なら解放時にshared_ptr<X>取れるじゃん、
修正とか色々めんどくさいけど、とかアホなこと考えてました。
処理の概略はshared_ptr側で値管理、コンテナ側は登録されたweak_ptrの値と別の値が合致したら処理、
shared_ptr側解放時コンテナ側から登録抹消(抹消関数の引数にshared_ptr:これがNG)というものです。
何でかshared_ptrって派生出来ないと思い込んでたけど出来た。
shared_ptrで出来ない理由は分からんが、他に変な問題が無ければほぼ当初の想定通り。
ありがとうありがとう。
template<class T>
struct X : public std::shared_ptr<T> {
X(T* t) : std::shared_ptr<T>(t){}
~X(){/*X自体の登録抹消*/}
};
クラス内部で
using std::shared_ptr<T>;
を付けるとコンストラクタの実装が完璧になるよ。
>>509 クラス内部で
using std::shared_ptr<T>::shared_ptr;
を付けるとコンストラクタの実装が完璧になるよ。
>>510 基底クラス(shared_ptr)のコンストラクタを派生側に引っ張って来る便利な奴ですね(覚えきれてない)。
ありがとうございます。自前実装不要なのは助かります。
>>508 それって本当に意図通り?
X のデストラクタが起動するのは X 型のオブジェクトが解体されるときであって
参照カウントがゼロになったときじゃないんだよ。
>>512 …あー。それは意図通りではないですね。実際の解放はデストラクタで
use_count()==1であることを確認する必要があるのかな。ありがとうございます。
パブリック継承した型では基底への型変換を禁じることができない。
つまり
X<int> foo = new int(1);
std::shared_ptr<int> bar = foo;
みたいなことが出来てしまう。
間違った使い方を想定するとキリがないから
なんでもかんでもガチガチに型を設計する必要はないんだけど、
この場合はどこかでミスりそうと思うので
私なら継承でスマートポインタの挙動をカスタマイズしようとはしないと思う。
>>514 御忠告ありがとうございます。
高々shared_ptr自身を解放するだけと思っていたんですが、色々難しいですね。
> パブリック継承した型では基底への型変換を禁じることができない。
そんな問題があるとは。
派生クラスのキャスト演算子は引っかからず、基底クラスの
コピーコンストラクタをいじらないと禁止出来ないっぽかった。
protected継承にしてみたら代入は出来なかった。うーん、他に問題が無ければこれですかね。
> 間違った使い方を想定するとキリがないから
> なんでもかんでもガチガチに型を設計する必要はないんだけど、
> この場合はどこかでミスりそうと思うので
> 私なら継承でスマートポインタの挙動をカスタマイズしようとはしないと思う。
候補はprotected継承(暫定)、shared_ptr相当自作、或いは他の未知なる何か。
しかし一番素直で的確に機能を実現可能と思っているのがshared_ptrの拡張なので、
別の形で実現する方法はどうも迂遠過ぎて自分には思いつかないです。
# shared_ptr側がデータ実体と登録したコンテナの情報を持ち、コンテナ側はweak_ptrで参照
なので流石に自作は無し、とりあえず他に致命的な問題が無ければprotected継承で実装して、
他により良い方法を思いついたらそっちに乗り換えることにします。
そういえばweak_ptr試してない…?と思って試したら当然の如く代入できなかったので、
public継承でほったらかします。
std::unique_ptr なら型引数でもデリータを与えることが出来て、
型引数が異なれば異なる型ということになる。
#include <memory>
template<class T> struct custom_delete : public default_delete<T> {};
int main(void) {
std::unique_ptr<int, custom_delete<int>> foo{new int(42)};
// ↓ 別の型なので移動できない。 エラーになる。
std::unique_ptr<int> bar = std::move(foo);
}
ところが std::shared_ptr では型引数でデリータをカスタマイズすることが出来ない。
解体は動的な型に従うという保証をしているので。
#include <memory>
struct foo {};
struct bar : public foo {};
int main(void) {
// 解体のときに foo ではなく bar の
// デストラクタが呼ばれることが保証される
std::shared_ptr<foo> x{new bar};
}
std::shared_ptr は動的な情報 (実行時の情報) を元に挙動が決まるというのが
設計理念なので削除方法をカスタマイズしたいならコンストラクタにデリータを渡す
というのが最も自然な形と言える。
std::shared_ptr を継承する形でカスタマイズしようとするのは
してもそれ自体は仕様に反しないけれど不自然だなぁとは思う。 (個人の感想です。)
一応発端の動かなかったコードを短くしたのでおいときます。
0.動機:shared_ptr<int>のdeleterでvector<weak_ptr>を削除したい
1.deleter内だとxは有効でuse_count 0だったけど、vectorのweak_ptrは無効だったのでvectorから削除できない。
2.shared_ptr<int>のデリータはint*に対するもので、shared_ptr<int>へのポインタはshared_ptr<int>の
デストラクタじゃないと処理できないけど、既製品だから外からいじられない。
3.んじゃ、手っ取り早くshared_ptr継承してデストラクタを使えるようにすれば?
というのが趣旨でした。
#include<vector>
#include<memory>
int main(){
std::vector<std::weak_ptr<int>> v;
std::shared_ptr<int> x(new int(3), [&x, &v](int* i){
for(int j = 0; j < v.size(); j++){
std::shared_ptr<int> t = v[j].lock();
if(t && t == x){v.erase(v.begin() + j); break;}
}
delete i;
});
v.push_back(x);
}
>shared_ptr<int>へのポインタはshared_ptr<int>のデストラクタじゃないと処理できない
これが無理っしょ
shared_ptrのデリータで他所様のオブジェクトもついでに解体したろっていう発想そのものが危険な香りしかしなくてゾワゾワする
「プログラム」作るのって、やってみたいけど、全然知らないから、教えて欲しい。
からのスレの目的で建てました。
>>524 がC++をやるのは早過ぎる
先にpythonでもやってみろ
次のプログラムを実行するとコメントのように出力がされ、mainの最後で例外が発生してしまいます。
なぜ例外が発生するかわかる方教えてください。
mainを通してnewは2回実行され、deleteも2回実行されるので空ポインタをdeleteしていることもないと思うのです。
#include <iostream>
using namespace std;
class Csmp1 {
private:
int x;
int* p;
public:
Csmp1(int n);
~Csmp1();
void disp() { cout << "x=" << x << endl;}
};
Csmp1::Csmp1(int n) {
x = n;
p = new int;
cout << "constructor " << x << endl;
}
Csmp1::~Csmp1() {
delete p;
cout << "destructor " << x << endl;
}
int main()
{
Csmp1 d3(300); // "constructor 300"と出力
d3.disp(); // "x=300"と出力
d3 = Csmp1(400); // "constructor 400"と出力し、その後"destructor 400"と出力
d3.disp(); // x=400と出力
return 0;
} // デストラクタが呼ばれ、delete の部分で"Unknowin signal"例外発生
>>527 d3 への代入で暗黙のコピーコンストラクタが使われている。コピーコンストラクタを適切に定義すれば解决する。
>>527 d3 への代入で暗黙のコピーコンストラクタが使われている。コピーコンストラクタを適切に定義すれば解决する。
>>527 d3 への代入で暗黙のコピーコンストラクタが使われている。コピーコンストラクタを適切に定義すれば解决する。
>>527 d3 への代入で暗黙のコピーコンストラクタが使われている。コピーコンストラクタを適切に定義すれば解决する。
連投すみません。コピーコンストラクタと、代入もです。
>>527 暗黙に生成される代入演算子は全てのサブオブジェクトを代入したような挙動になるルール。
ポインタを代入した場合には代入元と代入先のポインタが指す先のオブジェクトは同一なので
一方のポインタを通じて delete したならもう一方のポインタからオブジェクトに触れようとしてはならない。
(もう存在しないので。)
この場合は
d3 = Csmp1(400);
としたときに生成される一時オブジェクトはこの式が終わった時点で解体されるので
d3 内にあるポインタはデストラクタで delete 済み、すなわち無効なポインタとなる。
d3 のデストラクタが起動したときはデータメンバ p が指している先は無効なので
無効なポインタをいじったことになって問題が生じる。
それと d3 のコンストラクトのときに new したオブジェクトはどこからも delete されてない。
>>532-533 お二人さま ありがとうございます。
>d3 = Csmp1(400);としたときに生成される一時オブジェクトはこの式が終わった時点で解体される
右辺により生成されるオブジェクトが単にd3に格納されるのではないのですか。
それと入れ替わりに、d3コンストラクト時のオブジェクトのデストラクタが呼ばれると思ってました。
(どこからも参照されなくなるので)
自分が根本的に誤っている気がします、すみませんが上の内容でおかしい点を教えてください。
>>534 > 右辺により生成されるオブジェクトが単にd3に格納
JavaScript とか Python の動的型言語の経験があるのかな?
それとも Java や C# の参照型のモデルで考えてる?
C++ では左辺はメモリ上の特定の場所に対応づいていて、
別の場所 (右辺で生成される一時オブジェクト) にあるものを格納するというのは
コピーするということ。
その上で不要になった一時オブジェクトは解体される。
一時オブジェクトは一部の例外を除いて完結式 (完全式ということもある) の終わりのタイミングで
解体されるルールなのでこの場合は行の終わりが解体のタイミングということになる。
>>534 > 右辺により生成されるオブジェクトが単にd3に格納
JavaScript とか Python の動的型言語の経験があるのかな?
それとも Java や C# の参照型のモデルで考えてる?
C++ では左辺はメモリ上の特定の場所に対応づいていて、
別の場所 (右辺で生成される一時オブジェクト) にあるものを格納するというのは
コピーするということ。
その上で不要になった一時オブジェクトは解体される。
一時オブジェクトは一部の例外を除いて完結式 (完全式ということもある) の終わりのタイミングで
解体されるルールなのでこの場合は行の終わりが解体のタイミングということになる。
サーバから書込みエラーが返ってきたのを専ブラの機能でリトライしたら多重投稿になってしまってるな。
なんか不安定な状況っぽい
みんなでリトライするからF5攻撃並みに自爆DOS攻撃
>>527 int *をunique_ptr <int>にすると
コンパイルで弾かれるから
気づきやすいかもね
newとdeleteは直で呼ばない方が良い
newとdeleteを直で呼んでるかどうかと
今回の問題(コピーが発生してるかどうか)は
関係無いんじゃね?
>>540 「コピーが発生してるかどうか」とは関係ないのはその通り
>>527が恐ろしいのは
コンパイル時点では気づかず実行して初めて明らかになるところ
どうしたら実行前に避けるかの方策として
unique_ptrの常用を提案しました
>>527 に有効な解決策は
コピーコンストラクタじゃなくて
ムーブコンストラクタじゃないのかな
vector dp(N+1,vector(i+1,vector<mint>(i,0)));
これはdp[N+1][i+1][i]個のデータを確保していると思っておk?
>>535 を始めとして皆さんまたまたありがとうございます。
アセンブラ、Cを長くやってきたあと、最近C#を少し覚えたのでそちらと混同していました。
コピーコンストラクタと代入の演算子関数を作ろうとしていますがまだ途中。少しずつ進めます。
既製品のクラスライブラリについて、クラス階層が深いところのクラスは、公開メンバの全体をひと目で見渡すことができません。
マニュアルや継承のツリーををたどって地道に調べるしかないのですか。
>>549 ソースコードの構造を調べるのを補助するツールはあるが
どういう意図でどういう使い方を想定してそう書かれているのかは
プログラマが読み解かないとどうしようもない。
既製品ならドキュメントあるだろ
ドキュメントで謳ってないことはやるべきでない
visual studio community 2022で、
他のソリューションで作成されたmoduleをimportする方法がわかりません。
#includeみたいにパスを指定する方法とかがあるんでしょうか?
外部モジュール取り込みは言語仕様じゃ無くてIDEの機能だから
typedef uint8_t byte;
:
byte a = 3;
uint8_t b = a;
bの初期化は型不一致エラーにならないと思います。
コンパイラは型の異なる変数の初期化や代入を見つけると、typedefを探して元の型が同一かを調べてエラーにするかどうかを決めるのですか。
>>558 typedef は型の別名を作る機能であって新しい型を作らない。
Visual StudioでソリューションAでビルドしたブツ(.exe、.dll、lib)、シンボルファイル(.pdb)、必要なヘッダファイル(.h)
をソリューションBで取り込むの場合、Aのビルド後イベントとBのビルド前イベントを駆使してフォルダのパスは
"$(Solution)..\x\$(Platform)\$(Configuration)" みたいなマクロで解決、みたいなローテク頼みという印象、
Visual Studio 2019以降だと今は実はもっと簡単?
class MyClass {
public:
MyClass();
:
};
int main()
{
MyClass* c = new MyClass(); ①
MyClass d;
MyClass* dp = &d; ②
:
}
オブジェクトのポインタは①や②のように取得できると思います。
私からすると①はdeleteしなければならないのでできれば使いたくない。
①の書き方は、よく入門書に出てくる、継承関係にあるポインタの相互代入のためにあると考えて正しいですか。
>>561 自動変数の寿命はスコープ単位だから
それより長い寿命のオブジェクトが必要なら new する。
寿命の種類のことを Storage duration といい、
new で生成したオブジェクトは Dynamic storage duration に該当する。
継承関係がどうこうというのは何が言いたいのかよくわからないが、
ポインタの性質はオブジェクトの寿命とは関係ない。
相互代入は言葉がおかしいですね。
基底クラスのポインタで派生クラスのオブジェクトをポイントできるというものです。
オブジェクトのボインタを使う場面があまりないので用途を聞きました。
>>563 >自動変数の寿命はスコープ単位だから
それより長い寿命のオブジェクトが必要なら new する。
自分の場合、関数内より長い寿命が必要となったらそれはもうグローバルにしてしまいます。設計方針がよくないですかね。
>>564 グローバル変数として書いたオブジェクトの寿命は static storage duration に該当する。
この static というやつは main が始まる前に構築されて main が終わった後に解体されるので
必要以上に長い寿命になってしまうことが多いし、
実行時の情報を元にして構築するオブジェクトを static にはしようがない。
dynamic (new でのオブジェクト生成) が必要になる場面はごく普通にある。
ごく普通にあるのに使わずに済ませてるならたぶん不自然な設計になってると思う。
グローバル変数は寿命も長すぎるがスコープも広すぎる。
人間は自分が思ってるより馬鹿だから最初にどういう想定をしてたのか忘れて要らんことをしてワヤにする。
触らせたくないものは隠しておくのはカプセル化の考え方の重要な部分。
本当に人間は忘れるし間違える。
部品ごとに間違った使い方を出来ないように配慮しておかないと規模を大きく出来ない。
まあ逆に言えば小さいプログラムではそんなに凝ったことをしなくても大丈夫なんだけど。
>>561 >@の書き方は、よく入門書に出てくる、継承関係にあるポインタの相互代入のためにあると考えて正しいですか。
そのためだけにあるという訳ではない
>私からすると@はdeleteしなければならないのでできれば使いたくない。
生のポインタではなくスマートポインタ(unique_ptrやshared_ptr)を使えば
deleteはスマートポインタがやってくれる
構築は uniqu_ptr <MyClass> = new MyClass(); や
uniqu_ptr <MyClass> = make_unique <MyClass> (); のようにやる
> 基底クラスのポインタで派生クラスのオブジェクトをポイントできるというものです。
> オブジェクトのボインタを使う場面があまりないので用途を聞きました。
アップキャストのことだろうかね。
必ずといっていいほど使う機会がある。関数の引数にオブジェクトを渡すときとか
>>561 は、最初から必要数が決まっているオブジェクトしか作ったことがないのかな。
リストやツリー構造を自作していれば、①が必要なケースは分かると思うけど。
>>565 ほか皆さんありがとう。
自分の関わってきた分野が小規模組み込みだからか、そもそもCでmallocの使用経験がないのです。
処理系がmallocをサポートしないMCUもありました(使いたいなら自分で作ってという思想、標準入出力も)。
なので
>>568 さんの指摘は当たりです。
c++に挑戦している今の環境も小規模なので、newの利用はほどほどに検討してみます。
new 演算子はオーバーロードも出来て、型ごとにメモリの確保の仕方を変えるといったようなことも出来る。
メモリの確保と値の構築を別のレイヤとして定義できるということに意味がある。 (いわゆる関心の分離?)
低レイヤでも便利な場面はたぶんある。
分離する甲斐がないほど小規模ならべた書きが悪いわけじゃないけど
あえてべた書きという設計を選ぶってのとなんもわからんで使わないってのでは違う。
知っておくに越したことはないよ。
空配列を用意してそれを順繰り使い回す
チープなCPUでは必須の方法
よく
A a = new A();
a->b();
delete a;
みたいに生成してすぐ解放ってのがありますけど、
A a;
a.b();
じゃ駄目なんでしょうか。前者に何のメリットがあるんでしょうか。
後者はスタックを消費するから A が巨大なオブジェクトだったら困るとかかな
>>578 A *a = new A(); よね、一応
bを呼び出したいだけなら特にメリットはないよ
何したらここの人らみたいにプログラム詳しくなれるの?PC98からやらなきゃダメ?
>>578 > ありますけど、
ないよ……。
少なくともそう頻繁にはない。
あるとしたら
>>579 が指摘するように A が特に巨大な場合というのはひとつの可能性。
ただ、巨大になるのがわかってるならリソースを分割して A の中で
上手いことやりくりする (A 自体の大きさは抑える) べきで、
クラスを使う側で配慮しなきゃならないのは普通は悪い設計だと思う。
第二の可能性として、 new 演算子をオーバーロードして
そのオブジェクトがメモリの特定の場所に対応づけられる場合。
メモリバス経由でデバイスと接続するようなアーキテクチャもまあまあ有るから
それを C++ 上ではオブジェクトのように抽象化するということはあるかもしれない。
でもそれは低いレイヤだけの話で、
適当にラップするクラスを作ってもうちょっと抽象度の高いクラスを挟むのが普通だと思う。
PC9801 時代を知ってる人は色々と詳しいと思うがその知識が役立っているというわけでもなくて、 PC9801 時代からの三十年くらいあれば詳しくなって当たり前ってだけだぞ。
たくさんの知識を身に付けるにはたくさん学ぶというシンプルな話。
当時は役に立ったけど今はオワコンの技術と
今でも役に立ってる技術と
どっちが割合多い?
新しい技術的流行が昔からあったやつの焼き直しってことは珍しいことじゃない。
「なんや、結局は××やないか」というときに××自体が廃れていてもう使わなくても
理解のためには役立っているのでオワコンとも役に立ってるとも言えたりする。
ActiveXってCOMだよね
COMってOLEだよね
こんにちは坂本と申します。
C++を0から勉強したく書き込み致しました。
私ごとですが先月定年退職し、やっと自由な時間がもてる様になりました。
在職中ずっとプログラミングの勉強をしたかったのですが子育てや職場がプラントの電気機械保全業務の3交代だった為に定年後を楽しみに我慢してまいりました。
プログラミングの知識は全くなく制御盤のPLCでニーモニック語でリストプログラミングをするぐらいしか経験はありません。
有料でもかまいませんので何回でも質問ができ、すぐに返答と解説をして頂けるサービスや学習機関がございましたら教えて頂きたく書き込ませてもらいました。
漠然とした質問で申し訳ありませんが今月よりプログラミングの勉強を独学で始めましたが質問できる知り合いもいなく困り果てております。
長文失礼致しました。
C/C++ はポインターがあるから、ややこしい。
10年やっても無理
Ruby をやれ。
半年で、Ruby on Rails も出来る
ポインターが分からない奴は
プログラムを組む資格がない
ちゃんとした本があれば独学でそんなに困らないと思うけどな。
入門書の各章をじっくり読んで理解してから次の章に進むみたいな学習法をしているなら
詰まったときにどうしていいかわからなくなりがちなのでやめたほうがいいと思う。
色んな要素が相互に絡むので順番通りに学べるようなものじゃないから。
理解できなくてもたくさん詰め込んでいけばその内に繋がりがわかってくる。
「最初は」熟考しなくてもいい。 入ってない知識が関連するなら考えてもどうせわからん。
>>593 ポインタ使わないこともできるのに何言ってんだ
そもそもポインタはノイマンアーキテクチャの基本なのでポインタがわからないというならコンピュータの利点を十分に利用できないということ
ポインター: 変数が入っているアドレスの数字
なんも難しいことはない
インデックスって言えば分かる?
コンピュータにあるメモリー全体のインデックス番号
俺も最初全然わからなかったけどC言語ポインタ完全制覇のおかげで覚えた
Java や C# にもポインタはあるしポインタを理解できなかったら他の言語も使えないよ
ポインタ自体は難しくないんだけど C/C++ ではポインタ演算できちゃうのが鬼門なんだよね
ポインタの文法なんて入門書には必ず説明があるので直ぐ分かるとして
俺が初期に読んだ数冊の入門書には
それがプログラミングでどう役に立つのかが示されてなくて
悶々としながら読んでいたなぁ
ポインターなんて処理が糞遅いCPUをいかに速く動かすかって事以外に意味が無いからなぁ
std::string str = "abc";
①str = str + "dd";
②str = "dd" + str;
これらの記述は有効のようです。
①の右辺はstr.operator+("dd");
と解釈でき理解できます。
②の右辺は "dd".operator+(str);
と書きかえるとこれは無効に見えます。
std::stringのoperator+のプロトタイプを調べたところテンプレートが駆使されており私では読めませんでした。
②が有効なのは、テンプレートの仕組み?でそう書けるようにつくられているからですか。
>>605 非メンバ関数として定義されている。
つまり
str=std::operator+("dd", str);
に相当することをやってる。
メンバ関数として定義すると不都合が起こるから std::complex とかも非破壊的な二項演算子は非メンバ関数として定義するのが通例だよ。
>>606 本を見直したらfriendにするといい等ありました。
第1引数+第2引数、という記述があり、2個の引数を持つ+演算子関数が定義されている場合はそれが呼び出される決まりになっているのですね?
>>607 そう。非メンバ関数として二つの演算子を受けとる operator+ があれば a+b みたいに書いたときに operator+(a,b) に読み替えられると考えてよい。
(全ての演算子を非メンバ関数として定義できるわけではない。)
余談だけど ADL という変な規則があるのは演算子が名前空間修飾できないことに対処する必要があるというのが理由のひとつで、自分が定義するクラスではこれが上手いこと作用するように設計すると便利なこともあるかもね。
>>609 間違い。
「二つの演算子」じゃなくて「二つの引数」
最小のサンプルコードを書いて自分で試すと分かるし身につくよ
書いてみるというのは賛成。
でもあくまでも学んでから確かめるために書くのであって動作から言語仕様を推測したりはしないように。
C++ には未定義とか処理系定義とかがいっぱいあるからテキトーに書いたプログラムの結果が保証された動作とは限らないから。
>>612 >でもあくまでも学んでから確かめるために書くのであって動作から言語仕様を推測したりはしないように。
横から悪いがこれには反対させてもらう
もちろん動作からの仕様の決めつけは良くないが、人間は学習する動物なので書いて動作を見てこそ上達するんだよ
丸暗記だけで理解したと勘違いしてるやつが昨今多い(そしてそういう奴に限って何も作ってない)ので、そういうのを後押しはしないで欲しい
というか、自分の認識の間違いに気づくのもまた書いて試した時だからね(まれにコンパイラのバグだったりもするけど)
人間が頭の中で考えたことなんか穴だらけなんだから書いて試せるなら真っ先に試した方がいい
>>613 同意。
処理系依存とか未定義動作なんて中級者以上になってから気にすればいいこと
はじめは手元にある処理系の結果を「正」として学習を進めても問題ないと思う
>>598-599 ポインタ判らんって人はその辺は判ってんだよ
本当に判ってないのはアドレッシングモード
>>602 peek poke はあるし変数もあるから
用途という意味でのポインタはある
>>613 そうだな
Rust スレにも変なのが粘着してゴリ推ししてて迷惑
>>613 > 書いて動作を見てこそ上達するんだよ
だから書いてみるのは賛成と書いたのだが、何に反対してるんだ?
「学んでから確かめるために書く」
↑反対されてるのはここでしょ
これどうなるんだろう?動かしてみよう!なるほどこうなるのか!という学び方でもいいと思う
あなたが言ってるのは「これどうなるんだろう?」ではダメで「こうなるはずだ!」と学んでから動かせってことだよね?
それは初心者には結構むずかしい
>>621 > これどうなるんだろう?動かしてみよう!なるほどこうなるのか!という学び方でもいいと思う
私が言いたいのは推測できるものではないというところが主旨で、
自分が色々やってみたことが不確かな推測であることを認識した上で
きちんとした資料にあたって確かめるという順序でもかまわないとは思うよ。
出来るのならば。
やってない人が多いように私には見えているから否定的に言ってるわけだけど。
> 初心者には結構むずかしい
訓練せずに他のことをしてても出来るようにはならないでしょ。
やらなきゃずっと難しいよ。
C++ は複雑怪奇かつ規格改訂もあるのでベテランでも頻繁に仕様を参照するのが普通なわけで、
資料を参照するのを後回しにするような人間が後にそのような人間に変われるとは思わない。
「やってない人が多いように私には見えている」
多くの人が出来てないことを初心者に求めてもねェ
>>623 「推測した後には多くの人が資料を見ること」をやってないという話だぞ。
最初に資料で学ぶ人は体系的な知識が身に付くからそっちがオススメという話だぞ。
初心者に対して「言語仕様を推測したりしないように」「学んでから確かめるために書く」って言ってたよね
言語仕様を理解してからコードを書けってことでしょ?
>>624 先にも後にも資料(言語仕様)を確認しない人が多いんでしょ
そんな難しいことを初心者にまで要求してどうすんの
>>625 そうだよ。 言語仕様を理解してから書くのが好ましい。
理解する前に色々試すというやり方も許容しなくはないが、
それでも後では資料を見て仕様を理解するという前提があってのもの。
理解する前に色々試すタイプは資料を見なくなりがちという現実があると述べてる。
>>626 「資料」と「仕様」を使い分けて書いてるつもり。
直接に言語仕様を読めとは述べてないよ。
プログラムを書くときは色んな資料を参考にするので
入門書程度すらちゃんと読まない人がやってけると思ってんの?
ってことを言ってる。
え? 資料=言語仕様じゃないの?
「言語仕様を推測したりはしないように」って言ってたから言語仕様に関する資料を読んでからコードを書けという意味だと解釈したのだけど
資料=入門書程度なの?
・・・なんか言ってることが変わってきたね?
ちなみに「入門書を何冊か買って読みながら進めるといいよ」みたいな書き方だったらこんなに絡んだりしてないからね?
>>629 いや、そりゃそうでしょ。 最初から言語仕様を読めとか言わないよ。
入門書だって仕様書に基づいて書いてるし、基づいてない入門書だったらクソってだけ。
>>623 これをやってきたのがはちみつ餃子なんだよ
俺ははちみつ餃子の書き込みにいつも感心してるよ
>言ってることが変わってきた
うん、まぁ、はちみつはそういうとこあるから・・・w
ただまぁ、言語仕様に詳しい人の存在は(はちみつに限らず)非常に有難いんだが、
実際にソフト書く上で気にしなきゃいけないのは言語仕様だけじゃない
特定のソフトの個別の問題を解決するためのアルゴリズムについて、資料があるのか?と。(すでに出来上がってて公開されてるアルゴリズムが存在する問題などほとんど無い)
一番大事なのは論理的思考力であって、なんでもはなから資料をアテにしてたら逆にそれが身につかないよ
>>631 だとしたら、言語仕様を推測するな、未定義動作や処理系がどーのこーのとずいぶんと遠回しな言い方をしたねえ
入門書を読みといいよの一言で済むのに
>>632 それは別の話。餃子がエキスパートであることは否定してない
初心者の前に高いハードルを立ててC++を聖域みたいにするのはやめて欲しいのだ
どうも仕様オタク(言い方は悪いが、アマチュアという意味も込めて)な人達は、自分の知ってる世界が全てだと思い込んでるようで前々から問題だと思ってた
世の中、マイナーなAPIとかになると嘘を書いてることもあるし何も資料が無いことすらある
もちろん実際の動作から「今わかること以上」をわかった気になる(仕様を知った気になる)のは問題だが、
逆に言えば「仕様がこうだから間違ってないんだ」などと動作を確かめもせずに決めつけるのも問題だ
そういうのは結局本人の心的態度の問題に過ぎない
アルゴリズムは考えればわかることもあるかもしれんが、言語仕様は考えたってわからんし。
(想像はつくことも多いけど。)
> 書いてみるというのは賛成。
初心者はこれでもいい
> でもあくまでも学んでから確かめるために書くのであって動作から言語仕様を推測したりはしないように。
中級者以上になって言語仕様等に踏み込んだ学習をしようとするなら書いたもので仕様を測るのではなく「学んで」知るべし
と言う意味だと俺は
>>612を解釈してた
>>634 複雑難解な C++ を試させるのがハードルの低い方法だと主張したいわけ?
きちんと整備された学習ルートがあるという話なのにそれでハードルを上げてるとか言われるのは心外だわ。
「きちんと整備された学習ルートがあるという話なのに」
お前そんな話してたか?
あれよな
・初心者スレだからアドバイスはすべて「初心者向けの内容」
・初心者スレだけどアドバイスは「初心者向けの内容」と「その先を見据えた内容」
はちみつ大先生は後者だけど、ツッコミを入れたほうは前者で読み取っているから噛み合わないってだけよな、たぶん
>>639 まずは資料を読め (資料があるから) という主張を最初からしてるつもりだが。
「C++言語リファレンスを頭に叩き込め!!話はそれからだ」
でいいんじゃね?と俺は思っている
で、理解できない部分は入門書やサンプルコードを読んで理解する
まずは書いて試せという人もいるが俺はこの意見には賛同できない
プログラミング言語というのは日本語や英語などの自然言語と違って
少しでも間違えたら動かないし、C++の場合なら最悪システムが破壊される
理解できなくても動けばいいなどという考えの奴がいるからバグが量産されるのだ
ミスが許されないのはたとえば医者だな
医者は医者になる前に知識を詰め込むのが普通だ
知識もないのに外科手術をしたらどうなるか?
切りながら覚えろというのか?
プログラミングは手術と同様、まずは知識、次に技術が必要となる、と俺は思っている
【完】
>>640 初心者教育は二種類に大別されると思っていて、たとえば公立学校の授業でするような
興味がない層も含めて最低限の知識は与える教育と
学ぶ意欲があって専門知識と言えるようなものを身に付けようとする者に対する教育。
前者は「興味をひく」というところから考えないといけない。
理屈よりも楽しいと思えるようなやり方が必要になることもあるだろう。
後者は理屈を避けては通れない。
理屈の身に付け方には色んな方法論があるかもしれないけど
まずは書いてあるものを読め
(先人がそれを良いやり方だと思ってまとめてくれたんだから!
手を動かす必要があると思うところでは演習問題があったりもする)
という風に考えてる。
今は初心者であるかどうかは重要ではなく
ここで相談するような層は後者のルートのつもりでいると私は思って書いてる。
>>642 >理解できなくても動けばいいなどという考えの奴
誰の話?
>>644 わからないか…かわいそうに…
教えてあげなぁぁい
>>628 最近ChatGPTに全部聴いて済ます変なのが住み着いて迷惑だな
>>642 >医者は医者になる前に知識を詰め込むのが普通だ
>知識もないのに外科手術をしたらどうなるか?
>切りながら覚えろというのか?
言いたいことは判るが「最初の医者」はどうしてたんだろうな
君の言ってるやり方は「従順な職人」を育てるやり方としては正しいが
クリエイターを育てることは出来ない
>>642からの
>>645だからな
一見それっぽいこと言ってるようで全く中身の無い事を言うアホが長いこと住み着いてる(C++系だけなのか他もなのか)
突っ込まれると頭悪い煽り方しかしてこないからすぐわかる、玄人ぶりたいだけのアホだから相手しない方がいい
医者の下りはおかしい
医師は残念ながら完全な医学的知識を身に着けて
外科手術に臨む訳じゃないぞ
語弊を恐れなければ「切りながら覚える」側面もある
ちゃんとした資料で学んでないと用語が無茶苦茶だから
何を言ってるんだかわからないということが起こる。
言語仕様の理解が結果的に正しくてもそうでなくても。
「伝わればいいだろ!」みたいに言う人が結構いるんだけど伝わらないから困るんだ。
メンバ関数をメソッドと言ったりするのは誤解の余地はそんなにないと思ってたら
非メンバ関数もメソッドと言っている例を観測したことがあるし、
子クラスって派生クラスの意味で言ってるんだよな?
と思ってよく確認したら入れ子になったクラス (nested class) だったりするし、
クラス変数は静的データメンバの意味だろう (Ruby とかにはそういう用語があるし) と思ったら
静的でないデータメンバのことを言ってたというオチもある。
結果的に正しく使ってる場面ですら本当にその意味で言ってるのか疑わしくなる。
経験や感覚で書けるようになったとしても
まともな資料を読んでないというのはそういった形でコミュニティ内で有害なわけで
たまには思い違いがあるのはしょうがないが
学んでないし学ぶ気もないのを良しとは言えないよ。
>>651 いい加減にしろよ
お前何でそんな上からなの?
>>652 伝えようとしない態度を批判してるところに対して伝わらないことを書くのやめろよ。
何が言いたいんだ?
自己正当化しか考えてない人格破綻者に道理を教えてやる気は無い、自分で考えろ
ここを利用してる初心者は、仕様について教えてくれるはちみつには感謝すべきだが、彼はプロではないしソフトウェアを書き上げたこともほぼ無いアマチュアであって
C++の学び方や上達の仕方についてまでご高説垂れてるのを真に受けないようにね
C++は別に仕様を完璧に把握しなくても使える言語だし(そんな言語なら使い物にならない)、未定義踏みまくるのは彼のようにわざと常識に沿わないおかしなコードを書きたがる素人だけだから。
荒らす気は無いのでこれで終わりにする
完璧に把握しろなんて一度でも俺が書いた箇所があるなら指摘してくれよ。
書いてないことを主張したかのような風評を流してお前はなにをしたいんだ?
資料(この場合は入門書)を読んでから手を動かして学ぶというごく普通の手順を主張してるつもりだが、むしろそうじゃない方法でどうするのがよいと考えてるんだ?
学校だって座学でやったことを演習で実践してるだろう。
>ほぼ嫉妬
俺に言ってんの?
いずれにせよ荒らそうとしてる自覚はあるか?
>>658 どう考えてもお前が荒らしじゃん
人のことをアホ呼ばわりしてるし
>>655 言語仕様・未定義動作・処理系とか言ってたから完璧に把握しろに近いニュアンスだと感じた
メソッドではなくメンバ関数、用語を正しくつかわないと伝わらないとか言ってることがどんどん変わってる
お取り込み中すみませんが質問です
ダウンキャストという用語が是か非かです
ボクは不適切な用語だと思っていて
理由は
1) 言語の仕様に出てきていない
2) アップかダウンかについてももちろん仕様に無い
3) アップキャスト相当の操作は通常行わない
です
少なくともC++界隈でちゃんとした定義なんて出てこないですよね?
>>662 仕様の中を検索してみたら何故か例示のコードのコメントとして数か所だけ upcast という用語で書いてあるんだけど……
原則としては C++ 用語ではないと考えて良いと思う。
クラスの関係をスーパー/サブだとか親/子で言うのが混乱の元という理由で基底/派生という用語になっているので
方向をアップ/ダウンで言うのもおかしな話だし。
derived-to-base convertion というような用語は仕様書の文面にもあるので
アップキャストに相当するのはこの用語のはずだけど
base-to-derived convertion という用語は出てこないので
ダウンキャストに相当する直接の用語はなさそう。
冗長でも「××から〇〇への変換」みたいな言い方が公式なんだと思う。
ところであらためて JIS を見たら derived-to-base convertion の訳語は「派生基底変換」だった……。
to が脱落したらだいぶん雰囲気が変わってしまうでないの。
これは真似しないほうがいいかもね。
ただ、 C++ 界隈の中でも、というか規格の提案や検討に関する文面の中でも
アップキャスト/ダウンキャストという用語はまあまあ使ってるっぽいので
なんだかんだで一語で表せるってのは便利なんだと思う。
私は使わないようにしているけど。
すまぬ。 綴りが間違えてた。 concertion じゃなくて conversion だった。
レスサンクス
お手数おかけして痛み入ります
> 3) アップキャスト相当の操作は通常行わない
B *b = (B *)d; // もしもこれが必要な世界だったら
使い分ける?ための用語が欲しくなるのはまだわかるけど
D *d = (D *)b; // こっち方向にしかキャストしないんだから
区別する必要もないし、アップだのダウンだの余計なもんくっつける必要もない
…とはいえボクがいくらこう考えても
みんながそうじゃないから蔓延ってるわけで
> 私は使わないようにしているけど。
その一言で何か救われた気分になりました
一応補足
> B *b = (B *)d; // もしもこれが必要な世界だったら
B *b = d; // こう書くだけじゃ許されなくて
ダウンキャストって言葉は普通に使われてると思うが…
日本語版のウィキペディアなら
C++ - Wikipedia
https://ja.wikipedia.org/wiki/C%2B%2B に「dynamic_castは基底オブジェクトから派生オブジェクトへの変換(ダウンキャスト)を実行時に安全に行うための演算子である」とある
英語版ウィキペディアなら
Downcasting - Wikipedia
https://en.wikipedia.org/wiki/Downcasting マイクロソフトのリファレンスなら
dynamic_cast 演算子 | Microsoft Learn
https://learn.microsoft.com/ja-jp/cpp/cpp/dynamic-cast-operator にアップキャストとダウンキャストのことが書かれてる
rustに至っては嘆かわしいことに
https://doc.rust-lang.org/std/any/trait.Any.html > pub fn downcast<T>(self) -> Result<Box<T, A>, Box<dyn Any, A>> where T: Any,
上記トレイトのメソッド名に採用されている
あー虚しい
あーヤダヤダ
>>667 使われてるけど規格に定義があるような正式な用語ではないってことだろ
>>665 むしろアップ/ダウンだけでは状況を充分に表せないんじゃないかな。
ポインタを経由せずに値を直接キャストすることもありうるし
参照の場合かもしれない。
class foo {};
struct bar : public foo {};
int main() {
auto a = bar();
// bar から foo へのアップキャストってどれのこと?
auto b = static_cast<foo>(a);
auto c = static_cast<foo *>(&a);
auto &d = static_cast<foo &>(a);
}
>>669 一応マイクロソフトのリファレンスは正式だと思うが
まあマイクロソフト独自の規格ってなるのだろうけどな
あんなもんは認めないというのなら仕方あるまい
>>663 >仕様の中を検索してみたら何故か例示のコードのコメントとして数か所だけ upcast という用語で書いてあるんだけど……
>原則としては C++ 用語ではないと考えて良いと思う。
>クラスの関係をスーパー/サブだとか親/子で言うのが混乱の元という理由で基底/派生という用語になっているので
>方向をアップ/ダウンで言うのもおかしな話だし。
upcastとdowncastって一般名詞なのではないかな?
>>671 デファクトスタンダードだとは思うよ、個人的には使うことに全然否定的ではない
>>673 デファクトスタンダード
それだ
大正解
言語仕様の説明をするときには
>>670 のようなバリエーションの内のどれのことを言っているかで
事情が変わってくるので結局は具体的な場合を示さなければならず、
「アップキャスト」「ダウンキャスト」という用語で充分に説明できない。
(より詳細な場合分けをするので用語を使う機会がない。)
逆に言うなら「アップキャスト」「ダウンキャスト」という用語を使うときは
充分な補足説明が必要で、それをちゃんとやってるか? ってことでもある。
どうせ説明を付け足すなら用語の甲斐がないので
使う意味もそんなにないように思う。
念のために補足しておくけど、これは「言語仕様を説明するなら」という前提なので
そうではない状況で文脈を共有できていて
「アップキャスト」「ダウンキャスト」という用語で通じるという確信がある場面に対する意見ではないよ。
>>651 違う言語で比較するときはそういう用語の使い方になるケースが多いと感じる
「學んでいない」のとはまた別の問題だと思う
>>656 あいつは學校行ってないかも知れないな
なんでも試行錯誤で
挙句ChatGPTが完璧に教えてくれると勘違いしている
救えない
>>662 「ダブルポインタ」ってのも可笑しな使われ方してることが数多く観測される
アスペルガー症候群だって良いじゃないか?
何で差別的なことを書くのかね?
クラス内からのみ参照する定数配列のベストな書き方を模索しています。
まず
1、constメンバ変数にする方法。ヘッダに書くだけで手軽だが、オブジェクト生成のたびに領域が取られてしまい資源浪費。
2、staticメンバにする方法。
.h
static const int TABLE[3];
.cpp
const int TABLE[3]={1,2,3};
エラー。ほかに、{1,2,3}の場所をhに移動してみたりしたがすべてエラーになり断念。
3、cppにのみに書きhには書かない。
.cpp
const int TABLE[3]={1,2,3};
エラーにならず良好。ただこれだとクラス無関係のC風の書き方なので、別の翻訳単位とよ間で名前の衝突が起きうる?
名前の衝突なく、メモリ占有はただ一個で、資源節約につながるならconstexprも活用したい。ベストな書き方はどうなりますか。
constexprは上のconstを置き換えて試しましたが2ではエラー解消せずでした。
2のcppは
const int クラス名::TABLE[3]={1,2,3};
も試したはずですがエラー解消しませんでした。
2で通るはずだけどなぁ・・・ヘッダインクルードしてないとか?はさすがに無いか
あとC++17以降ならstatic constexprにすれば暗黙的にinline変数(定数)になるのでなお通るはず(宣言と同時に=ヘッダで定義できる)
あ、ごめん2で通るはずってのはcpp側がクラス名::TABLEの場合
2、staticメンバにする方法。
.h
static const int TABLE[3]={1,2,3};
.cpp
extern const int TABLE[3];
もれはやらんけど
あ、ごめん逆だった
.cpp
static const int TABLE[3]={1,2,3};
.h
extern const int TABLE[3];
>>684 出来なかったというコードをそのまま提示して欲しい。
状況がよくわからないのに想像で対処法を考えてもしょうがない。
コードがちょっと長くなるなら
codetter とか wandbox とか ideone とかを使って。
クラス内の定数を外部に生出しとかしないから
enunとかで宣言はするけど
何番目が欲しいとかはサービス関数作るしなぁ
つか、static宣言の内部でしか使わないものを何でヘッダーファイルに書くの?
ヘッダーファイルはクラスコードの名刺みたいなもんで
外部にこう言う事が出来ますよってPRする為のファイルなんだから、普通は内部で完結してるものは書かないよ
マジックナンバー避ける為に#defineするとかも、cpp側の先頭に書くと、全ビルドしなくて済むしな
>>692 staticには複数の意味がある
>>683 の発想は h に static 描いてみたら「たまたま」エラーが消えたら ok みたいなやり方なんだろ
>>695 staticより「内部でしか使わない」って話の方を拾ってね
>>696 質問者は「クラス内からのみ参照する」って言ってただろ
>>697 それならヘッダーファイルに書く必要無いやんけw
そら綺麗に一つのcppに全部そのクラスの実装を切り分けてるならcpp内にstaticでいいだろうけどね
>>680 > 「ダブルポインタ」ってのも可笑しな使われ方してることが数多く観測される
それなw
初心者ほどこの用語を使ってるように見える
初心者が集まるところでこれを流布してるやつがおるんやろな
ポインタへのポインタっていうスケーラブルな定義が理解できてなくて
アスタリスクいっこのポインタと、二個のぽいんたがある!って感じなんやろな
>>700 この
>>699 の言は逆のことを言ってると思う。
ひとつの翻訳単位にたくさんのクラス (の実装部分) を書くこともあるから
ファイルスコープにしたらスコープの範囲が広すぎる (制限にならん) やんけと言ってるように読める。
>>700 巨大とかじゃなくて、あんたの考えてるであろう1ヘッダに1ソースってのも指針としてはもちろん良いんだけど(そして質問者のケースに合ってるならいいけど)
例えばクラステンプレートになると、ソースに実装を書けないからヘッダのどこか(ヘッダからインクルードしてユーザーに見え辛い場所には出来るが)で実装を書くことになる
そうなるとその実装からソースファイル内のstaticな値など見えるわけがないだろ
まぁどれを選ぶかは本人の都合だけど、クラス定義の中にprivateで書くのが自然っちゃ自然な希ガス
>例えばクラステンプレートになると、ソースに実装を書けないから
C++の設計ミスだな
特にテンプレ
テンプレートは単なる#defineだからなぁ
あんなもん#defineでの置き換えによる副作用を引き起こす悪習の最たるもんだよ
一応はモジュールの概念の導入でちょっと良くなっているはずだが皆でこぞって移行するってほどには全然なってないからそこまで魅力的とは思われてないんやろね。
従来のスタイルと共存できるようにするのは C++ の立場では当然ではあるものの、悪い部分も捨てきれないことになりがち。
コンパイラのサポートもあまり熱心ではない(?)ような雰囲気だからそこも不安だし。
どうも
>>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;
}
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に現れない上の書き方がいいと思いますが、これを最適としてよさそうですか。
解決おめ、自分の用途に合うと感じるならそれがベストと思うよ
h に static 描くと単に相互干渉しないってだけで
インスタンスは造られまくって無駄リソース出まくるんじゃね
sizeof(クラス名)を活用できる場面はありますか。
メンバによってはCのsizeof(構造体名)と同じ使い方ができると思いますが、
クラス一般について考えると思いつきません。
たとえば
std::string name;
がメンバ変数にあるともう、クラスのサイズは不定になりそうです。
あっ、new は・・・いや、mallocと違ってサイズ指定は不要ですね。
>>714 >std::string name;
>がメンバ変数にあるともう、クラスのサイズは不定になりそうです。
確認してみましょう!
>>714 sizeof 演算子の適用結果は定数であることが保証される。
定数式として使うことができる。
std::string なども型の大きさが変動したりはしない。
C ではオペランドが VLA のときは sizeof の結果は定数にならないのだけれど C++ には VLA がないのでそういう例外はない。
(実際には処理系の拡張として VLA を使える場合もある。)
メモリアロケーションまわりを自分でコントロールする機会があれば普通のクラスの大きさを知る必要がある場合もなくはない。
それほど機会は多くないだろうけど。
本来 (?) の用途とは違うところで使われる場合もあって、
いわゆる SFINAE のトリックで sizeof が使われることもそれなりにある。
>>716 高度な領域では使う場面はあるが、入門者には当分、なさそうですね。ありがとう。
>>717 stringも実際には確保したメモリのポインタと文字列サイズを持ってるだけ(だけではないけど簡単に言えば)なので
Cの構造体と大して変わらんのよ
まず鍵を与え、文字列を暗号化等して暗号文文字列を返したい。
暗号化ユーティリティ風のクラスをつくり、鍵とstringを渡す案 (1)と、stringを継承して鍵保持メンバ関数と暗号化メンバ関数を追加する案(2)を思いつきました。
どちらがでも実現できるように思いますが、何か設計のポイントはありますかね。
暗号化等には既製ライブラリ使います。
>>720 設計は総合的な判断だから単発の事情では判断しづらいというのは前置きとして書いておくけど、原則的には非メンバ関数として実装するほうがよい。
というよりも継承を使うほうが悪い。
「こういうメンバ関数があると便利」ということだけが理由なら継承を使うのは好ましくない。
プロジェクトの中で使う文字列を暗号化機能付きの文字列クラスで一貫して扱うならそれはそれでそんなに悪くないけど、通常は std::string 型のオブジェクトがあってそれを暗号化したいだけなのに別の型に変換にするという手間をかけるのがユーザーにとって便利だと思う?
他の選択肢としてはストリームのアダプタにするとかいう方法も思いつく。
極端に大きなデータ (メモリに格納するには無理のある大きさ) にも対処したい場合は入出力と並行して処理することになるから、普通にストリームに書き出すのと同じように使ったら勝手に暗号化されてるというのは使う側としては楽でいい。
自分が使うものならそういう余計な抽象化層を挟むのは手間なだけかもしれないし、匙加減は微妙なところ。
sqliteとかの(暗号化もあるけど)暗号化しないバージョンのDBを使ってて
書き込むとき勝手に暗号化してくれると有難いな
>>721 ありがとう。
非メンバ関数として実装、と見て最初はなぜ?と思いましたが、確かに文字列変換だけでクラスオブジェクトはいらないですね。
string 暗号化(鍵, 平文);
だけあれば十分だと。
msys2で開発環境を作りたくて
Windows10上にmsys2をインストールしてそのうえにpacmanからmingw-w64-x86_64-toolchainの最新版をインストールして
g++でコンパイルしてHello Worldを出力するところまではうまく行ったのですが
std::ifstream ifs("hoge.txt");
のような実行ファイルと同じ場所にある、あらかじめ用意したテキストファイルを読み込むだけのコードを書いてもファイルの読み込みに失敗します。
fstreamだけの問題ではなくfilesystemあたりをインクルードして適当な関数でテストしてもファイルが存在しないことになっていました。
どこで質問するのが適切なのかも見当がつかない状態なのですが原因に心当たりがある方がもしいらっしゃったら教えて頂けないでしょうか?
msys2 環境は数種類のモードがあるはずだがどれで起動した?
実行ファイルの場所がカレントになってないんだろ
getcwd()してみ
エラーは何もなくて変数に何も格納されてない状態だったので原因よくわかりませんでしたが
今回は
>>731さんの言う通りになっていて解決できました
まだmsys2自体の仕様も十分に理解してなくて手が回っていない状態なのでこれでいったん失礼します
ありがとうございました!
GUIから起動するとカレントディレクトリがホームになるんだったっけ?
OSの事情でカレントが簡単に移動してしまうのがめんどいな
プログラムの実行に必要な設定ファイルやデータファイルはカレントディレクトリではなく実行ファイルのパスを基準に決めたほうがいいね
設定ファイルの類いは AppData フォルダに置くのがこのましいということになってる。
アプリケーションインストール用のフォルダ Program Files は書き込み権限が制限されているからそこに設定ファイルは置けない。
逆にどうしてもアプリケーションと設定ファイルを同じフォルダに置きたいなら Program Files にはインストールできない。
Msys2 内で使うソフトならホームディレクトリ (windows のホームディレクトリではなく msys2 が設定するホームディレクトリ、環境変数 HOME で取得できる) に設定ファイルを置くのが基本的な習慣。
起動時の引数や 自分のフルパスを取得するAPI経由で
実行ファイルのある場所を基点にどうこうすることが多いわ (Windows
unix だと usr と bin で分ける文化があるからそういうのはどうなってるんやろか
起動時のカレントのまま?
>>736 それはインストーラー使うアプリでしょ?
XCOPYインストールアプリの話だよ
カレントじゃ無くて、アプリが実行されたディレクトリに一緒に置いとくもんだろ?
ユーザー毎に違う設定にしたいなら、各ユーザーのホームディレクトリだろ?
>>739 基本的にはそうだけどパッケージマネージャの管理方式との相性があったりする。
scoop で管理するなら設定ファイルも含めてひとつのフォルダに入れるほうが都合が良いと思う。
Msys2 内で pacman で管理するなら unix 風の流儀のほうが自然だし。
グローバル位置に宣言したオブジェクトはmain前にコンストラクタが実行されますね。
仕様ではmain前に実行ということのほかに何か規定はありますか。
ある処理系で、main先頭である処理を呼び出すと成功するが、その処理を上記のコンストラクタから呼び出すと失敗するということがありました。
>>741 ややこしい規則が色々あってここには書ききれないがおおざっぱにはこんな感じかな。
・ 定数初期化が終わってから動的初期化がされる
・ 動的初期化でも条件が揃ったときは静的初期化扱いで早めに初期化する最適化をしてもよい (しなくてもよい)
・ 翻訳単位内の初期化順序は定義が現れた順序
・ 翻訳単位をまたぐとどちらが先に初期化されるかは規定されていない
特に翻訳単位を跨いだら決まってないってのは引っかかりがちなポイントで、
強い依存関係のあるものはあまり細かく分割しないほうがやりやすいと思う。
普通は、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",
相談室から誘導されたのでこちらで
http://2chb.net/r/tech/1698705458/104 buf_にPODではないオブジェクトが含まれる可能性がある場合、この領域をどのようにcopyしたりmoveすればよいでしょうか?
このスレッドはゼロからC++と言っているが、C言語を知っている前提になっているよなw
ワシも割と長く底辺コピペプログラマだけどなんでそんな詳しくなれるの?ってなる
有能と俺みたいな無能はどこでプログラマの生き方をたがえたのか
>>746 頭の出来で決まっているからね
義務教育レベルで脱落した人間、日本語能力に問題がある人間は、プログラマーとしても問題がある。
知識は入れないと増えないというすごく当たり前の話。
長く放置してたら勝手に増えるなんてことはないよ。
ガキの頃からマイコンBASICマガジン見てたけど
PCなかったしポケコンはあったからたまにあるポケコンゲームのソースをポチポチ入力してたけどそれで何かの知識になったか言われたら何にもならんかったな
>>749 SHARPのポケコンでマシン語使ってシューティングゲーム作ったけど?
ポケコン触ってたころが一番楽しかったです
手の中に物理キーボードと実行環境があるんだもん
一生遊べるよ
>>744 memcpyでなくちゃんとplacement newでコピーorムーブコンストラクタ走らせればいんじゃね?
Class Hogeの中でたくさんのFugaを管理するために
std::vector<std::unique_ptr<Fuga>>というメンバ変数を作りました
可変長引数テンプレートで複数のstd::unique_ptr<Fuga>を受け取るコンストラクタを書こうとしたのですが
std::unique_ptrがコピー禁止のためうまくいきませんでした。
Hoge(Args&&... args)
という形で右辺値参照を受け取ってうまいことムーブしてClass Hogeを初期化する方法ってありますか?
>>754 できると思うけど、何をやりたくて何が上手くいかなかったのかイマイチわからない。
出来なかったコードをみせて。
>>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がコピー禁止でエラーになったのでムーブにしたいけど書き方がわかりませんでした。
>>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));
}
>>757 無事に動作させることができました。ありがとうございます!
時間のかかる処理があり、それが現在のスレッドをブロックして欲しくないので
その処理の部分に関してstd::async()の利用を検討していますが、
これって戻り値(future 型)でモニターしないといけない感じですか?
上記の処理はいつ終わるかは気にしないので別スレッドに投げっぱなし?で構わない
のですが... pthread_detach()的な?
>>761 std::thread のメンバ関数に detach はあるけど、期待するのはこういうこと?
ただ、メインスレッドが終了すれば他のスレッドが稼働中でもプロセス終了処理に入るし、
プロセス終了処理の中で標準ライブラリの後始末している最中に他のスレッドが
標準ライブラリを使うようなことがあると破綻するかもしれない。
強引に終わらせて良いなら std::quick_exit で即死させるという方法も取れるが、
基本的にはプログラムを終わらせるときには全てのスレッドを終了させて (終了を待って) おくのが
普通だと思う。
>>761ですが、お返事ありがとうございます。
はい、とりあえず thread::detach() を使うようにしました。1つの疑問は、
https://ja.cppreference.com/w/cpp/thread/future/~future によると
> ただし、その共有状態が std::async によって作成され、まだ準備完了になっておらず、これがその共有状態への最後の参照である場合は、ブロックする可能性があります。
ええ何それ、というのが発端でした(後出し失礼)。
確かに、メインスレッドの終了時のこともありますし、スレッドの後始末をちゃんと
した方が本当はいいように思われます。処理が長時間たっても終了しない場合
タイムアウトさせたりとかも。
何かシステマティックな方法等あるでしょうか。参考になるものがあれば...
>>763 メインスレッドの終了直前でまずは適当にフラグを立てた上で他のスレッドの終了まで待機する。
重い処理をしているスレッドの側で完了ではないにしても区切り良く終われるポイントでフラグを読んで
フラグが立っていれば後始末ルートに入ってスレッドを終了させる。
その結果としてメインスレッドの待機状態が終わってプロセスの終了。
というのが普通の大まかな流れだと思う。
その上で待機時間があまり長すぎるようだと強引にでも終わらせるとかの処理を入れるかも。
std::async は既存の関数を非同期化するちょっとしたユーティリティという立場なんじゃないかな。
それで事足りるときは便利で簡単だけど、細かい制御を勝手にやってくれるわけでもないし、
やろうとするとちょっとイマイチって感じ。
質問なのですがどんな環境(ロケール設定)の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()が上書きしないように見えるのですがそういうもの?
>>765 言語仕様通りならそれらの関数を呼び出さないようにすれば環境に固有の表現の変換はしない。
std::setlocale の設定が C の標準関数の挙動に影響するのはその通り。
ただし、様々な環境での「同じ動作」を期待するなら "C" を与えるべき。
空の文字列を渡した場合には環境に固有の設定であり、通常はシステムの設定が反映される。
プログラムは起動したときに setlocale(LC_ALL, "C"); 相当の状態なので、普通は書く必要もない。
std::locale::global での設定は C++ の標準ライブラリの挙動に影響するだけでなく std::setlocale での設定にも反映されるので両方を呼び出す必要はない。
これもプログラム起動時のロケール設定は "C" 相当になっているのでそれで良ければ呼び出す必要もない。
ただし、 std::locale::global に与える設定が名前を持たない場合 (つまり std::locale("") のような場合) は std::setlocale 相当の変更もするかどうかは規定されない。
imbue はストリームにロケールを結びつけるのでグローバル設定とは独立して機能する。
クラスオブジェクトの代入文に、=による単純コピーと、=演算子関数による独自コピーのどちらを使うか迷います。
たとえばメンバ変数が基本データ型の集まりなら単純コピーでいい。
今出くわしたのはメンバ変数がstd::array<int, 3>の場合で、まあたぶん単純コピーでよさそう?じゃあstd::vector<myclass>なら?などと疑問が深まります。
あとコピーコンストラクタによる初期化も合わせて考える必要がありそう。
>>767 単純コピーってのは何のこと?
デフォルトで生成される代入演算子の意味で言ってるのかな?
>>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" で行こうと思いまつ
>>769 Windows での話か……。
msvcrt だとどうにもならなくて ucrt でちょっとマシになってるみたいな話題をこないだ Teratail で見たぞ。
>>770 デフォルトで生成される代入演算子は全てのサブオブジェクト (基底とデータメンバ) を
代入演算子でコピーするのと同じ挙動になることになってる。
基底やデータメンバが適切に代入演算子を定義されているのならデフォルト生成にまかせてよいことが多い。
注意を払う必要がある典型的なものは生ポインタで、
ポインタをコピーしても指してる先のオブジェクトはひとつだから
そのへんの扱いはデフォルト生成だとあかんことになる。
あとは外部のリソースと結びついているオブジェクトだと単純にコピーできないか、コピーさせないこともあるな。
分かりやすい例で言うなら std::thread なんかはスレッドを抽象化したものだけど
オブジェクトをコピーしたらスレッドもぽんぽん増えるなんてことになっても困るし
スレッドひとつに対応しているオブジェクトがいくつもあるようでも困るのでコピーできないようになってる。
それぞれに事情があるので明瞭な判断基準があるわけじゃないけど、
デフォルト生成の結果がほんまに自分の意図通りに動作するか考えてみて
あかんなら自分で書くしかない。
>>772 いつもありがとうございます。
たいていはデフォルトでよさそうですね。
std::vectorは可変長配列ってことなので、<int>であってもデフォルトでいいのかなと心配に…あこれはvectorのほうで独自=定義されてるなら問題ないわけですね。
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
}
>>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
}
>>775 横からだけども
> X x2 = 2; // b:NG(conversion from 'int' to non-scalar type 'X' requested)
って
X x2(2);
と同義じゃねーの?
>>776 違うよ。
C++ では引数ひとつのコンストラクタは変換コンストラクタとして「も」使うことになっているから
違う文脈でも結果的に同じコンストラクタが呼び出されることになるけど
構文糖というわけではなくて違う解釈を経ている。
動くなら同義と考えても大した問題じゃないが、
ここでは実際に結果が違う (一方はエラーになる) ことの説明だから……
これはなぜエラーになるのですか。
std::string s = "abc";
char name[10] = s.c_str();
error: array must be initialized with a brace-enclosed initializer
次と同等とみなせないのはなぜ?
char name[10] = "abc";
>>775 774だけどありがとう。暗黙だと変換が途中で途切れるかもなのか。
一番通って欲しいのがbなんだけど難しいっすね…
>>780 c_str()が返すのはchar*
char name[10] = "abc"; は特別扱いで char name[10] = {'a', 'b', 'c', 0}; と同じ
cの時からある雀の涙猫の額ばかりの文字列サポート
>>781 少し表現を変えて良ければ
>>774 の X x2 = f0; を
X x2 = {f0}; と書くことでも通すことは出来るよ。
更に真面目に対処するならこんな感じかな。
https://wandbox.org/permlink/giXZnCETo64IkEez >>783 上は={}で通るのは確認してました。{}付けるとX型に見なされてコピーコンストラクタで初期化されるで合ってますか?
下の方、typenameの所は余りよく分からなかったですが強制的に引数の型で包んで(オブジェクト生成?)、コンストラクタの引数代入時に変換追加するということでいいですか?
typename以下はdecltype(f_)((f_))でも良いんかなと思って変更してみたら通りました
>>785 > {}付けるとX型に見なされてコピーコンストラクタで初期化されるで合ってますか?
いいえ。 直接初期化に該当します。
コピー (コピーコンストラクタの起動) は発生しません。
つまり X x1(f0); と書いた場合と同じということです。
ですから暗黙の変換を一段階すれば充分なのでエラーなく通ります。
> コンストラクタの引数代入時に変換追加するということでいいですか?
いいえ。 何もしません。
コンパイルを通すためには不要ですので、 X のコンストラクタは
template <class T>
X(const T& f_) : f(f_) {}
という定義だけでも問題なく動作します。
ただ、こうすると T は「あらゆる型」になりえます。
std::function<void()> に変換不可能な型も受け入れてしまうということです。
変換不可能であればいずれにしても最終的にはエラーなのですが、
X がデタラメな型も受け入れてから F に変換失敗してエラーになるよりは
特定の条件を満たす型以外を X が拒否するほうが一般的には都合がよいので
そうなるようにしたのです。
コンパイルを通すために必要なのではなく通さないための処置です。
>>786 上:初期化周りは似たような物が色々あって知識が曖昧でした。
下:あの記述は型制限の為ですか。読んでも意図がよく分からなかったので助かります。
説明ありがとうございました
質問なのですが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)と同じパティーンで復旧がマニピュレータ……
>>788
・ 直接的に入出力を司るのはバッファと呼ばれるオブジェクト
(たとえば 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 から。 >>789 ㌧クスなるほど……
変更した書式の戻し忘れが無く、問題らしい問題点はほぼ無しで良さげ……
(しいて言えばstreamの中の作りを理解していなければtempが何の目的でそうするのかわかりにくい(コメント必須)なだけ、
std::printは手元のVC++がまだC++20対応止まりなので当面見送らざるおえない
std::formatは…… 書式文字列が定数式限定という仕様のはいかがなものか……
今回の用途では困りませんし、コンパイル時に書式の妥当性をチェックしてくれるのは良いのですだが、
仮に、C言語における自作printf()様インターフェースの関数(書式文字列と可変長引数を変数で受け取り、内部でvprintf()を呼ぶ)
みたいなものを作りたくなった場合どうするんじゃとそこはかとなく疑問が……
>>790 実行時バージョンとして std::vformat も用意されている。
>>791 なるほどなるほど、自作std::format()様関数は問題無く作成でき、
書式文字列が定数式限定が困るというのは杞憂ですたねサーセン;;;
(実行時にならないと書式文字列が決まらない場合、コンパイル時チェックが原理的に不可能になるのはC言語のprintf()/vprintf()の関係も同じなのでC言語からの後退ではない
メンバとして copyfmt があって、これで書式を他のストリームにコピーすることも出来る。
書式を待避しておくだけのストリームを作ってそれにコピーしておいて
後で元に戻すという使い方をしてもいいんだけど、
どうせストリームをあらたに作るならそれを一時的なストリームとして使ったほうが自然かと思う。
std::setのinsertで
std::set<int> c1 = {1,2,3};
std::set<int> c2;
c2.insert(c1);
と書けると便利に思えますが解説のページを見るとできないようです。
なぜですか。
>>794 c2.insert(c1.begin (), c1.end ());
>>794 set に set を insert できる「だけ」ってのはあまり便利ではない。
集合というものをより汎用的に扱える枠組みとして C++20 から range という概念が導入された。
その枠組みを上手いこと成立させる言語機能 concept が長いこと検討されてて、
入る入ると言いながら C++20 までずれ込んでしまったという事情がある。
そんなわけで、 C++23 からなら insert_range が使えて、
これは range の条件を満たすものならなんでも受け入れられることになってる。
>>794 c2.merge(c1) ※C++17以降
みなさんありがとう。環境適合を優先して
>>795を使うことにします。
コンストラクタの初期化子リストの中で、どこまで柔軟に記述できるのかなーと思ってGPT先生に聞いたら、constまたはconstexprを返す関数のみ書けるとのことでした。
コンストラクタ内部のように好きなように書けないとわかり、初期化子リストの価値が低く感じられました。
そんな制限を設けてまで初期化子リストを導入した意図は何でしょう。
ChatGPTなんかあてにするな、平気で間違ったこと言うんだから
constやconstexpr以外を返す関数だって普通に呼べる
試しにChatGPTに「メンバ初期化子リストではconstかconstexprを返す関数しか呼べませんが、これはなぜですか?」ってあえて間違った前提条件で質問してみたら、間違ってることに対する指摘は一切なかったし、さもこっちの質問が正しいかのようなそれっぽい返答が返ってきたし
---
俺:
C++において、コンストラクタのメンバ初期化子リスト内ではconstまたはconstexprを返す関数しか呼ぶことができません。これはなぜでしょうか?
ChatGPT:
C++において、コンストラクタのメンバ初期化子リスト内でconstまたはconstexprを返す関数しか呼ぶことができる理由は、初期化子リストがオブジェクトの初期化に使用され、実行時のコードが生成されないためです。メンバ初期化子リストはコンストラクタの一部であり、オブジェクトが生成される際に実行されます。このリスト内での関数呼び出しはコンパイル時に解決され、オブジェクトの初期化に関する情報は実行時に生成されません。
constまたはconstexprを返さない関数をメンバ初期化子リスト内で呼ぶと、実行時にコードが生成される可能性があります。しかし、これはオブジェクトが生成される前に行われる初期化の一環であり、実行時の処理としては不要なオーバーヘッドを引き起こす可能性があります。
コンストラクタのメンバ初期化子リストは、メンバ変数を適切に初期化するためのものであり、できるだけ効率的に行われるように設計されています。そのため、コンパイル時に解決されるconstまたはconstexprを返す関数の呼び出しに限定されています。
---
だからAIをあてにしちゃダメだよ
>>800 私が聞いたときも似たような内容が含まれていて、そうなんだねと納得してしまいました。
ではコンストラクタに書けることはすべて書けるのですね。
なおこの問いは、入門書籍にはそこまで書かれてなくて、検索でもかんたんに見つからなかったので聞きました。
>>801 たぶん
>>799 で言う「初期化子リスト」は「メンバ初期化子リスト」だよね?
これらは全くの別物。
明らかに混同しやすい用語だから仕方がない部分はあるんだが、
誤った用語を元に調べたら誤った解説に当たりやすいかもしれない。
メンバ初期化子リストは直接初期化 (direct-initialization) であると規定されていて
具体的な挙動の説明は初期化の章に丸投げされている。
https://timsong-cpp.github.io/cppwp/n3337/class.base.init#7 つまりメンバ初期化子リストに特有の事情というものはない。
普通に初期化なんで、そこに違いがあるかもしれないという想像をする人がいてそういう人のために
違いが無いと断りを入れる必要があるとは入門書の著者は思わなかったんだろう。
有るものを有ると説明することはあるが無いものを無いと殊更に強調して説明はあまりしない。
>>802 そうですメンバ初期化子リストです。どうもありがとう。
なお書籍には、メンバ変数名(引数)やメンバ変数名(0)の例ばかりでした。
すみません、コンストラクタの宣言/定義で A() {}; とした場合と A() = default; と
書いた場合は何が違うのでしょうか。挙動とか意味だとか...
あるいはある種のタイプクラスの場合は違いが生じるので注意とか....??
>>804 default を指定した場合はデフォルトのルールでコンストラクタを生成する。
生成可能な条件が満たされなかった場合でもそれ自体はエラーにはならずに
デフォルトコンストラクタは削除済と見做されるというルール。
そのときはデフォルトコンストラクタを必要とする使い方をした時点でエラーになる。
つまりこんなことをしてもエラーは出ないが
struct foo {
foo() = delete; // デフォルトコンストラクタを削除
};
struct bar : foo {
bar() = default; // デフォルトコンストラクタのデフォルト生成
};
int main(void) {
}
↓ こういうことをするとエラー
struct foo {
foo() = delete; // デフォルトコンストラクタを削除
};
struct bar : foo {
bar(){}
};
int main(void) {
}
>>806 遅レスすみません。要は、コンストラクタの特定のパターンの用法をされたくない
ときに使う感じ? でそれに該当するとコンパイルエラーになるわけですよね?
自分が気になったのは、ランタイム時に何かありうるかということです
あるコードで、コンストラクタがdefault指定されているクラスが、別のクラス内
(親子関係にはない)でunique_ptrとして生成されたときに問題が生じたような
感じで....
ってもっと自分で調べてからレスしろって話ですが、現在そのコードに立ち戻る
ことができず、とりあえず疑問だけを
C++ の仕様は場合分けで規則がごちゃごちゃしていることが多くて単純な一般原則として説明できない。
「要は」なんて一言でまとめられないよ。
>>807 そういう目的ではないと見ていいよ
>>806が言ってるのは、基本的にはデフォルト実装でコンストラクタを作ってくれるが必ずではない、と言ってるだけ
デフォルトの(引数無しの場合、何もしない。が、基底クラスの引数無しのコンストラクタはちゃんと呼んでくれる)コンストラクタでいい場合に使う。
A() {}と書くのと基本同じだよ
異なる型を含むような配列(的なもの)を作りたいのですが、可能でしょうか?
例えば template <T> struct NamedValue { string name; T value; } を定義して
NamedValue<string>{a, b} や NamedValue<int>{c, d} などの型の異なる複数の値を、
一つの配列的なものに収納したいのです
例えばvectorは全要素が同じ型じゃないと駄目ですよね
あるいは要素数がコンパイル時に決まらないなら
std::anyをコンテナに入れるとか?
はい、要素数はコンパイル時に決まらないのでstd::anyのコンテナですかね
で要素を取り出すときは、どの型なのかをチェックして挙動を...
もし
>>810 の T の種類が限られているのなら std::variant を使ったほうが楽かもしれない。
std::visit を使えば型の種類ごとに処理を切り替えるのが便利なことがある。
std::remove()ってファイルを消去する関数なんですね
std::move()と名前が似ているのに全然違う
名前空間か関数名にfileくらい入れとけって思うよね
C言語以前にE言語の問題や
さすがにそのくらいの英語の勉強はしておけと思う
C の規格から取り込んだものだから由来が違うんだよ。
今なら std::filesystem::remove があるからこちらを使うほうが良い作法だと思う。
>>815 >std::remove()ってファイルを消去する関数なんですね
std::remove()ってSTLのstd::removeじゃなく?
ちゃんとコンテナの要素をre-moveしてると思うが?
>>819 だよねえ??
>>815-818が何を言ってるのか分からなくて怖い
ああ
<cstdio>に
int remove( const char* pathname );
ってのがあるのか
https://en.cppreference.com/w/cpp/io/c/remove >>818 なるほど。諸般の事情でC++14な環境で、ファイルを扱う関数を探していたら。
Boostに行く手もあるかもしれませんが、とりあえず。
cstdio のは std:: 名前空間じゃないよね.
::remove だと思うけど
>>823 cstdio にある関数は std 名前空間にある。
ただしグローバル名前空間「にも」あって良い。 (無くても良い。)
stdio.h の場合はグローバル名前空間で宣言されるが std 「にも」あってよい。 (無くても良い。)
言語そのものではないのですが、コマンドラインのデバッガやIDEでSTLのコンテナの内容を
易しく表示してくれるのってありますか?
例えばvectorなら、単純に中の要素だけを列挙してくれたりとか
ビルドにCMakeを使っているのでとりあえずCLionを使っていますが、これは
確かに変数の中身をリスト構造で見れますが、変数内の生のメンバー(M_なんちゃら等)
見えてる感じで、STLコンテナに関してはあまり親切ではないような
デバッグの際は見えた方がいい場合もあるのでしょうが。なら表示が切り替えられたりとか?
自分はmacOSですが、他のプラットフォームにしかないものも参考に聞いてみたいです
今からC++を勉強するならC++20を基準にやっても構いませんか?
最新の規格で勉強して必要に応じて古い知識をつけていくような学び方でいいの?
C++ は基礎の上に段階的に応用が乗っかっているような綺麗な構成ではない。
全部が入り組んで捏ねまわされてグダグダや。 そんでもってクソ巨大やねん。
どこから入っても同じ。
質問なのですが
std::string には std::to_string(int)他の簡単文字列化関数がありますが
std::basic_string<T> に対する簡単文字列化関数はどう?
>>826 WindowsのVisual Studioではできる
最初に学ぶ言語がC++なら、Cより学ぶのが大変じゃん
やっぱ数値からstd::basic_string<T>の文字列への変換とかTが決まらないとやり方がわからないから
std::basic_string<T>でそれをやりたい人が対応せよ(std::basic_string<T>版to_string()やstd::ostrstreamをT毎に作成せよ)という天の啓示?
証拠にstd::wstringについてはstd::wstring to_wstring(int)とかstd::wostrstream とかある
OS上で動かすアプリ作りたくなったからC++とC#で悩んだんだけどどちらの長所も捨てがたい気がして両方学んでみるかな?って思ったんだけどC++でのおすすめの参考書とかあります?
一応、学生時代にC言語で五目並べとファイルの出力までは勉強してます。
一応ググって入門参考書とか調べましたがちょっとC言語齧ったのなら実戦的な例題集みたいなのが良いのでしょうか?
あとこの質問スレ違いだったらすいません。
Windows上のアプリをC++で作るのは少々ハードル高いが
個人的にオススメなのはWindows2000 プログラミング標準講座(ハーバート・シルト著)ってやつ
C++そのものの本は他の人が挙げてくれると思う
どういう学び方が良いかは人による。
C++ の設計思想としては理解できた便利機能をその都度に導入する形で学んでいけるようにという配慮はしていると設計者は言っている。 実務でプログラミングをしてる人は「C++ をちゃんと習得するまで待ってくれ。 仕事を止めてくれ」とは言えないからね。 C を理解しているならとりあえず C のように書きながら部分的に C++ 的にしていける。
つまり実戦的な学びかたも一応はアリ。
ただ、実戦的な学習はやりたいことが出来てるならそれ以上深掘りする意欲につながらない。
C の書き方でやれるなら別の形に積極的に書き直したい理由って何?と感じてしまうことがある。
きちんとした理解に至らぬままの中途半端な形になりがち。
やりたいこと (書きたいもの) が明白なほうが道筋は付けやすいんだけど、やりたいことに邁進しすぎてもそれはそれで「学習」としてはイマイチなんだよ。
そのへんは程度問題というか匙加減というか、人による、場合によるとしか言いようがない。
個人的にはしっかりとした理屈っぽい入門書を一冊は読んでから方針を決めればいいと思ってる。
>>838 レス、ありがとうございます
Windows2000 プログラミング標準講座が近所の図書館にもなかったのでそこにある蔵書読んでみてVisual studio使ったプログラミングしたことないからそれをツールとして使った入門書でいいかな?って思ってしまいました。
>>839 レス、ありがとうございま。。
何を作りたいかの方向性でそれに使うものだけ勉強すれば速いというのはわかります。
自分的には作りたいアプリもあるけどまずGUIアプリを作るための基礎からやりたいなと思ってます。
理屈っぽい入門書の理屈っていう部分はプログラムのハードでの処理の考えとかかと思ったのですがそれはたぶん理工系の学部行ってたので通信情報の基礎理論は聞いたことあるので大丈夫だと思います。
C++は基礎わかってれば後は組み込みたい機能のコードを探せばいいってことと解釈してコード集みたいな辞典を使ったり、ネットで調べたりすればいいってことでいいのでしょうか?
>>840 私がいう「理屈」は言語仕様のことのつもりで言ってた。
低レイヤから入った C ユーザーは C を使えているようでも言語仕様に対する理解が浅くなりがちで、
良くも悪くも機械語 (ハードウェアの挙動) と対応づけて考えてしまうところがある。
言語としての抽象とその実装は分けて考えないといけない。
現代的なコンパイラは最適化がメチャクソに賢いので実際に生成される機械語と一対一には対応づかないし、
言語仕様で未定義としているところを踏んだらわけのわからない動作を引き起こすので
言語仕様について一定以上には身に付けてから実践を始めないと何がなんだかわからないことだらけだと思う。
逆に一定以上に C++ の基礎を身に付けてからならあとはリファレンスを見ながらでも行けるけれど、
今の C++ の「基礎」は昔の C++ と比べるとかなり巨大になってしまっているので当初の C++ の設計思想のように
C から段階的に C++ を身に付けるってのはあまりお勧めできないと私は考えてる。
C++ はとにもかくにも巨大で言語機能はお互いに絡み合っているので部分ごとの理解なんて出来ないんじゃないかということ。
繰り返すけど、人による。
自分なりにどういう方向性で行ったらいいのか判断するためにはどこからでもいいから一旦は始めたらいい。
どうせまったく躓きなく進むなんて出来ないんだから駄目だったときにどこが駄目だったかを検討して
軌道修正するしかしょうがないんじゃないのかな。
>>840 一応Amazonで中古が出てる
最近の本を知らないのでなんとも言えんのだけど、
Visual Studioと名のつく本は、開発環境(VisualStudio)依存の機能使いまくりで他で応用が効かないんだわ、本を選ぶときの参考にしてくれ
(開発環境に依存しまくりでいいなら、ぶっちゃけC#のがはるかに楽)
>>838はWin32APIやメッセージループとかの「ずっと変わらない基本」をちゃんと教えてくれる本として挙げた
>>841 言語仕様ですか
私自身、自分はハードを動かすためにCやアセンブラ触った口だから多分それに該当しそうです。
>>842 ちょっと気になったのですがハーバート シルト(著)の標準講座C++とか独習はどうなのでしょうか?
ハーバート・シルト氏の著書を少々調べてみたのですがどれも人によっては難しいとコメントあるけど素晴らしい学習書という人が多いみたいでしたので
>>843 C++ の仕様は不変なわけではなくてたまに改定してるというのは考慮に入れる必要がある。
どの仕様かを言うときには改定年度を付けて表す通例があって、現時点では C++98, C++03, C++11, C++14, C++17, C++20, C++23 がある。
入門レベルなら最新を積極的に追うほどの必要はないけど、最低限度は C++11 だと思う。
改定の期間があいたせいでインパクトの大きい変化があった。
それより古い書籍は良書だとしても現状に合わないところは色々とあるかもしれない。
GCC や Clang は特に指定しなければ C++17 モードのようなので現時点の基本は C++17 くらいというのが一般的な認識なんじゃないかな。
あーそういや独習書いた人だっけ
独習は定番レベルで評価高い、ある程度Cの知識は前提になるけど読めると思う
C++標準講座は読んだことないのでわからんすまん
なに?プログラムって。むつかしそうだなー
ぜんぜん知らないんだけど、ちょっとやってみたいなー
ってな人も、入れてあげてね。
そういうスレなんだから。
質問です。
独習でc++勉強してるのですが掛け算して出力するっていう練習問題見ててふと気づいたのですがこの本一体どの文字コードで保存すること考えて書いてるんだ?っていう疑問が出てきました。
sjisだとちゃんと日本語表示されるけど汎用性ないよな?ってことでUnicodeで書くこと前提で勉強したほうがいいよなって思ったんですが下のコードだと何を直せばいいのでしょうか?
#include <iostream>
using namespace std;
int main()
{
double hours, wage;
cout << "労働時間を入力する: ";
cin >> hours;
cout << "時給を入力する: ";
cin >> wage;
cout << "合計賃金は" << wage * hours << "円\n";
return 0;
}
>>847 データの型としては unicode を扱えるようになってるけどコンソールは言語の外の話なので Unicode を扱えるかどうか、使えるにしてもどう切り替えるのかは言語仕様としては決まってない。
Unicode で出力は出来るけどそれを理解して表示できる環境かどうかはわからないということ。
>>847 つまり、自分のところの文字エンコード使えってことでしょうか?
動作的には目的通りできますし、環境次第で文字表示はどれ使えるか変わってくるしで
>>849 実行環境はこの環境で使えるプログラム組めるまで気長にやるつもりなのでなしです。
setlocale()使ったことないのでよくわからないのですがロケール宣言してその中で日本語使ってみたらってことですか?
>>850 言語仕様には書いていないことだから実行環境 (OS やターミナル) のドキュメントを読んでねってこと。
色々な文字コードをサポートしていることもあるししてないこともある。
切り替えることが出来ることもあれば出来ないこともある。
それとストリームはリダイレクト (接続先の変更) される可能性がある。
やりたいことによっては
標準出力がターミナルに繋がっているときとファイルに繋がっているときを区別しなきゃならないかもしれない。
Unix 系 OS の場合はテキストを表示するのはターミナルで、ターミナルはごく普通のアプリケーションのひとつ。
OS 自体はアプリケーションとターミナルの仲立ちをしてるだけなんだけど……。
Windows の場合は標準のテキスト画面 (コンソール) は Windows に標準的に備わった特別なもの。
その特別なテキスト画面を使ってる間は Windows のドキュメントに書いてある通りにすればいいのだけど
Windows で別のターミナルを使うときはその制御方法の規格が確立してないから
主要なターミナルを判定して場当たり的な処理をしているのが現状。
近年は ConPTY という規格が使われ始めてるけどどんなターミナルもそれをサポートしているってわけではないから
結局は場当たり的に対処すべき対象が一個増えただけって感じ。 (将来的には統一されるといいなぁ……)
更に Windows は C ランタイムサポートが文字コード変換の機能も持っていて接続先を勝手に判定して
変換することがあって、その挙動がかなりわけがわからない。
色々あるけどまとめると「こうすればいい」という簡単な説明が出来ない入り組んだ事情があるって話。
すいません。
私の環境ただ単にUTFが使用可能になってなかっただけでした。
termcap/terminfoとか
init.d
inittab
getty
人間に匹敵する知能を持った汎用人工知能を開発した研究者に総額100万ドルの賞金を授与するコンテスト「ARC Prize」が開催
>>847 C++は、日本語対応していないよ、注意してね。
だから、"あいうえお"なんかのコードは実行されない。
俺はこれを理解するのに10年以上かかった。
>>858 No.
現在は Unicode についての規定はあるし、 Unicode のコードポイントに対応つくことが保証された文字列リテラルはある。
俺のエディタは、EmEditor Professional (64-bit)だ。
だ。だからC++は、C++17だ。
わからなかった。ごめんな。
C++と文字コードに関してはこの記事が面白かった
https://qiita.com/yumetodo/items/54e1a8230dbf513ea85b 俺もあまり詳しくはないから全部理解できた訳じゃないけど、筆者の人がブチギレまくってるのを感じ取るだけでも面白かった
>>857 どうやってチューリングテストするんじゃ……
coutやcinとかなiostream系の入出力手段のうちのワイド文字でないやつは
エスケープ文字('\\'とか)や書式指定文字('%'とか)に依存しないから
つまりたまたまマルチバイト文字の一部が '\\' や '%' に一致してもなんら実害が無いから
Shift JISの入出力が問題を引き起こすことは無いという認識でおk?
>>863 言語仕様的にはテキストモードでは実行環境の都合で各種の変換を入れても良い。 (入れなくても良い)
実際に Windows では文字コードや改行コードの変換をする。
改行が \r\n であるようなテキストを読んでも内部的には \n であるように扱えたりしてるのを不思議に思ったことない?
変換するということは変換元が想定通りじゃないときには破綻する可能性がある。
Shift JIS を使う設定にしてないときに Shift JIS を渡したら駄目かもね。
バイナリモードではバイト列そのまま。
Linux だとテキストモードとバイナリモードは区別がない。
>>864 だいたいわかりた、
>実際に Windows では文字コードや改行コードの変換をする。
テキストモードにおける '\n' <--> '\r\n' 変換をやるだけでも、
cout << "アイウエオカキクケコ\nさしすせそ" << endl;
と書かれたうちの '\n' と endl の2箇所だけ正確に変換するためには、
上記1行の中に暗黙に含まれるSI/SOおよび2バイト文字の「区」を表す上位バイトを
「実行時に」解釈する必要がある
つまりランタイムはASCIIのつもりで文字列を解釈しては駄目で、
Shift JISというものを知っている必要があり、これが
>Shift JIS を使う設定にしてないときに Shift JIS を渡したら駄目かもね。
につながるんだと思う。
しかし
>実行環境の都合で各種の変換を入れても良い。
とC++の仕様には書いてあると言っても実際には透過的でない文字コード変換とか有り得ないんでないので?
例えば
ofstream ofs("foo.txt"); ofs << "アイウエオカキクケコ\nさしすせそ" << endl; // (1)
std::string s1, s2;
ifstream ifs("foo.txt"); ifs >> s1 >> s2; // (2)
とやったらs1、s2とも中身は(1)の記述をコンパイル時に解釈した通りになる、
という期待動作しかありえないのでは……
具体的には
s1の中身は SI アイウエオカキクケコ SO の12バイト(末尾NUL除く)になって、
s2の中身は さしすせそ という10バイト(末尾NUL除く)になる、
いやトチ狂ったスマンヌ、
Shift JISの2バイト文字は上位下位ともコントロールコード('\r' や '\n' を含む)とはバッティングしないから
>>865 の理解はやや的を外していた……orz
テキストモードにおける '\n' <--> '\r\n' 変換は、ランタイムがShift JIS文字列をASCIIとして解釈してそれを行っても何ら問題を生じない。
しかし、であればやっぱ
>>863に戻って、実は実害無いのでは……
Shift JISの2バイト文字は上位下位とも数字とかともバッティングしないようになっているし……
透過的でない文字コード変換(
>>866)が無い限り、cout して cin して結果が変になるケースが思いつかなsげ……
(正確には char c; cin >> c; で 2バイト文字 "陰" の2バイト目を "A" として受け取ってしまう、系の避けようが無い事故は除く
>>861 その人ブチギレてるフリしてるだけの厨二病だから・・・
std::functionって関数の「比較」はできないんでしたっけ?
例えばあるクラスが std::function<..> m_callback みたいなインスタンス変数を持ってて
そこにコールバックを登録できるメソッドがあるとします
registerCallback(std::function<..>& callback) { m_callback = callback; } みたいな
で、registerCallback(func)が呼ばれた後、正しいコールバックが保持されていることをテスト
したいのですが、例えばregisterCallback()の引数に渡したstd::function<..>のオブジェクトと
m_callbackはどうしたら比較できるでしょうか。単純に == ではエラーになる模様です
>>870 メンバ関数テンプレート target を使えば元の関数を取り出せる。
https://wandbox.org/permlink/3sCREueD2sVYMW9t ただし、取り出すときに元の型を指定する必要がある。
ただの関数ならば簡単なのだけれど、
ラムダ式から直接に入れた場合には適切な型を指定できない。
ラムダ式が生成する値はそれぞれに固有の型を持つので。
一旦 std::function に入れたらあまり取り出さない (取り出す必要がない) 設計が望ましいと思う。
テストのためだけなら大丈夫だと思うけど。
functionではなくオーバーロードで生の関数や関数オブジェクト(ラムダ含む)を受け取って、functionと共にアドレス値を保存すればいいのでは
関数オブジェクトの場合はoperator ()のアドレス
独習でc++を勉強していて時々プロセッサとかライブラリ関数これなんだろ?になるのですがそういうの調べる辞典的なものってあるのでしょうか?
あるのでしたらおすすめのもの教えてもらえませんか
ググって出てくるようなのは誤った記述も多い。
あまり信用しすぎずになるべく複数の情報源を持つのが好ましいと思う。
言語仕様は改訂もあるから資料の日付を見てどの版に対応するのかも意識する必要がある。
>>874 が示すような有志がまとめているサイトはちょっとした企業よりも高いモチベーションがあるのか質は高い。
本当にありがたいサイトなので役に立ったと思ったらちょっとくらいは寄付してあげてね。
いや、プラットフォーム固有って言ったのは
Microsoft Learn(旧MSDN)とかApple Developerとかのことやぞ
安価忘れてた、
>>875ね
複数の情報源持つべきとかは同意するけど
プラットフォーム固有のは公式が一番信用できるに決まってる(ただMicrosoftのは機械翻訳になってから日本語版がアレだけど・・・)
>>874 >>875 ありがとうございます。
やっぱ、ググって調べるのが一番なんですね。
ただ、C++と言いつつほぼCの内容で紹介してて本でやってる課題とこの関数の使い方知りたいでなんか食い違いあったんですがここわかりやすそうなので助かります。
手元に置いておく辞典系の本があっても良いと思うけどちょっとお勧めできるものを知らない・・(C++11より前のものしか買ったことない)
秋葉原とかの技術系の書店で手に取って読んでみるのがベストなんだけどねぇ
>>882 1万円くらいで転売しようと考えています
unordered_map の extract というのはC++17以降でしか使えないのですか
ここでGoogleTestの質問をしてもよろしいでしょうか?
質問なのですが派生とshared_ptr<T>を組み合わせたときに、
class Base {
int m_x;
protected: // Baseクラスのコンストラクタはprotected
Base(int x) : m_x(x) { }
virtual ~Base() { } // 仮想関数にしてもしなくても同じ下記現象
};
class Derived {
public: // 派生クラスのコンストラクタはpublic
Derived() : Base(10) { }
};
std::shared_ptr<Base> pBase(new Derived());
とやったら
error C2248: 'Base::~Base': protected メンバー (クラス 'Base' で宣言されている) にアクセスできません。
と言われるんだけどなんで?その判定要る??
自己解決しますた
文句が言われているのはBaseのコンストラクタでは無くてデストラクタか……orz
本当に解決したの?
それDerivedがBaseを継承していないよ?
あっはい
class Base {
int m_x;
protected: // Baseクラスのコンストラクタはprotected
Base(int x) : m_x(x) { }
pulic: // Baseのデストラクタをpublicに修正 // (1)
virtual ~Base() { }
};
class Derived : public Base { // 誤記訂正 // (2)
public: // 派生クラスのコンストラクタはpublic
Derived() : Base(10) { }
};
std::shared_ptr<Base> pBase(new Derived()); // (3)
(1)で解決、(2)は誤記訂正
文句言われたのがBaseのコンストラクタだとすると(3)においてDerivedのインスタンスがshared_ptr<Base>に渡される時点で呼び出し済なので
(3)でコンパイルエラーになるのは辻褄があわなくね?!と思った次第
文句言われたのがBaseのデストラクタだったからだいたい理解すた
(std::shared_ptr<Base>はあくまでBaseしか知らないから、Base::~Base()がpublicでなかったら
呼べないという解釈でエラーにするのは当然な可能性
std::unordered_map<std::string, std::unique_ptr<int>> map があった時のmapの管理について
教えてください
この場合値の方がunique_ptrなのでコピーはできませんよね。すると値を取り出す時は
foo = std::move(map["hoge"]); としないといけない?
で、moveしたあとは hogeに対する値は無効になっちゃってますよね。ということは
自分で消さないといけない? map.erase("hoo")とかで
>>893 >この場合値の方がunique_ptrなのでコピーはできませんよね。すると値を取り出す時は
>foo = std::move(map["hoge"]); としないといけない?
「値を取り出す」をどういう意味で使っているかによる
単に中身を読むだけならmoveしなくても良い
>>893 その考え方で正しい。
std::unique_ptr をムーブすると抜け殻のほうのオブジェクトは nullptr を指すようになることは保証されるが、
そのスマートポインタ自体が std::unordered_map から勝手に消えたりはしない。
消えて欲しいならそのための操作は必要。
std::unique_ptr 自体はコピーできないがそれが指しているオブジェクトを読むだけなら出来るしコピーすることも出来る (コピーコンストラクタを削除していないなら) 。
標準講座C++―基礎からSTLを利用したプログラミングまで 新装版 ハーバート シルト著が気になったのですがこれで勉強したことある方いますか?
>>899 読んだことは無いけど 2009 年発売ってのは微妙な部分かもと思う。
2011 年の言語仕様改定がインパクトの強い変更を含んでいて基本的な書き方の習慣に大きな変化があった。
そこらへんの事情が含まれない本だと現状にそぐわない。
weak_ptrが処理の途中で解放されてしまうのを防ぐために lock()を呼んでshared_ptrを
取得してから処理、というのがありますが、
lock()を呼んだ時点で既に解放されていることもあるわけですよね?
確かにlock()の戻り値をチェックして不正な呼び出し等を防げるのはありがたいのですが、
そもそもオブジェクトが既に解放されているのは残念といいますか。
lock()を呼んでからする処理の場所に来るまでに解放されないようにしたい、と思った場合、
どうしたらよいのでしょうか? もしかしてそもそもweak_ptrを使うな、ということになります?
既に寿命が切れてる場合はlock() が無効な shared_ptr を返すのでそれで判定する
lock() を呼んだ後は戻り値の shared_ptr が寿命を伸ばすので問題ない
shared_ptrは「有効なshared_ptrが1つ以上ある間はオブジェクトの寿命が消えない」ものなので、lock() が返すshared_ptrを保持してる間は消えないよ
lockを「weak_ptrからshared_ptrへの昇格を試みる」ものと考えても良い
lockしたい箇所の時点で必ずオブジェクトが生きていて欲しいなら、それはweak_ptrでなくshared_ptrを使うべき
>>899 2000年くらいにSTLはこれで勉強したよ
基本的なことは網羅されているが
C++の新しい仕様には対応してないので
別途学習すべし
いまもっと良い本があるかは分からない
C++の仕様は建て増しなので
この本に書かれていることは無意味ではない
>>900>>904
返答ありがとうございます。
今同著者の別の本で勉強中ですが基本的なところでこれも買っとこうかな?って質問しました。
基本参考書として買ってみます。
基礎的なところ終わったら自分が作りたいプログラムに必要な現状の本でも買ってみます。
すいません。誰か下のコンパイルオプションわかる方いますか?
解いてた問題の解答にも文字化けするって書いてあったので文字化け対策のオプションなんかないかな?って思って調べたらこのオプションで解決できるって出てたので使ってた人の入力例そのままオプション挿入してみてちゃんと解決できたから気になって調べたんですがググっても出てこなくて入力例が次の行のやつです。
g++ test.cpp -finput-charset=CP932 -fexec-charset=CP932
-finput-charset
-fexec-charset
ああなるほど、意図せずマイナス検索状態になってたから一件もヒットしなかったってことか
あるある
>>899 シルトは有名
ロベールも有名だったけど、
C++11 に対応していないので古い
STL標準講座、1999年
ハーバート・シルト 著
επιστημη(エピステーメー) 監修
この本も古い。
確か、エピステーメーはC++ の標準化委員だっけ?
C++テンプレートテクニック―簡潔で再利用しやすいコードのためのC++活用術
επιστημη/高橋 晶【著】、2009
独習C++ 新版、2019/11
高橋 航平 (著), επιστημη(エピステーメー) (監修)
>>909>>910
ありがとうございます
てか、検索でそういうことあるんですね
>>903 了解です、どうもありがとうございます
>>902 一般的なことを知りたかっただけなので
変数名の付け方について教えてくだち
Objectの個数、とかは nobjs とか objcnt (類例: argc)とかは本に載っていてそれぞれ
nobjs --- number of objects の短縮表記
objcnt --- object count の短縮表記(名詞obuectが形容詞的活用
となって対応する同じ語順の英語表現がある気がするのですが
<limit.h> の INT_MAX、INT_MIN はmaxやminがなぜ後置?
何の短縮形?
minやmaxの後置と前置の使い分けとは一体……
>>914 C は一貫した名付規約 (naming convention) を定めていないし、主要な処理系が持っていたものを追認する形で仕様に入ることもよくあるので起源ごとに名前の方式は異なる。
慣例はおおよそ踏襲されるのでもし新しい整数型が追加されたらそれの最大・最小値は同じような名前で表されると思うけれど全体を通したルールはない。
MIN_LONG, MIN_SHORT, MIN_USHORT だとmin まで同じで探しにくい
INT_MAXだとINT_ まで打てばコード補完できるけど、逆の語順だとMAX_ まで打った際に各型の候補がズラーっと並ぶことになる
当時は高級なエディタは無いし、多分そんな意図で命名してないと思うけど 、便利と言えば便利
意味を考えるならそれは max of int でなく、intという空間におけるmaxという値 (言語によってはint.max と書くような値) と考えると良いと思う
C++ならstd::numeric_limits使おうよ
>>915
>全体を通したルールはない。
えええええええ……
迷える子羊は一体どうしたら……orz
>>917
それはそうかもしれんが
std::numeric_limits<double>::min()ではなくてstd::numeric_limits<double>::lowest()なのがイマイチなカンジ
あと
while ((*p <= CHAR_MAX && isspace(*p)) {
p++;
}
とかのときは<limits.h>のがお似合いに思える…… 些細なことにこだわんな
複数人で開発してる以上そういう揺れはどうしても起こり得る
受け入れて先行け
object count, count number of object
integer maximum, maximum of integer
…同じじゃね?
全体を通した名前の指針としてはマクロは大文字でそれ以外は小文字 (スネークケース) ってくらいかなぁ。
関数形式のマクロは小文字なのもあったりと例外はいくらかあるけども。
今ってクラス名とか割とキャメルケースじゃないですか? DocumentWindowみたいな
一方でC++自体は小文字とアンダースコアで
でも意外とちぐはぐな感じはない。むしろ予約語、システム的なものは小文字で
ユーザー定義のものと分離されていていい感じ?
>>922 C++ の大元の設計者である Stroustrup は言語の技術的な詳細 (文法上の役割?) を名前に埋め込むことを嫌がってる。
https://www.stroustrup.com/bs_faq2.html#Hungarian クラスだから、ユーザ定義だからという区別を名前に入れるべきじゃないという考え方を取ってるわけ。
その一方で言語としての縛りは入れないという方針も著書に書いてある。
思うところはありつつも個々の場面は言語ユーザの判断にゆだねるってことだね。
C++ は C++ だけで完結するわけじゃなくて色んなシステムと接続することもあるからその都合に合わさないといけないこともあるだろうし。
たとえば Windows だと多くの API がキャメルケースなわけで。
私自身にはクラス名をキャメルケースにするのはちぐはぐに見えている。
でも出自が違うライブラリを組み合わせるならそういうこともしょうがないとも思ってる。
クラスや変数名に異なる命名を敵用するといった考え方が出てきたのがおそらC++登場の後だから仕方ないという感じ
C++は他の言語ほどには統一されたルールはない
自分は個人的に以下のルールを採用してる
おそらくPythonやRustあたりのルールに近い
・型の名前 (クラス、構造体、enum) は PascalCase
・変数と関数名は lower_snake_case
・定数とマクロは UPPER_SNAKE_CASE
・クラスのメンバー変数は value_ のように末尾にアンダースコアを付ける
・構造体のメンバーはアンダースコアなし (変数と同じ)
上記もあくまで個人的な意見に過ぎないので、プロジェクトの方針があるならそれに合わせるのが良いと思う
あと基本的な命名ルールも言語によって変わるので、その言語内に慣習やルールがあるならそれも見ておくと良いと思う
例えばC#はメソッドを PascalCase にするなど、上記とは異なる慣習がある
標準ライブラリは型が lower_snake なんだけどね
(std::string とか std::vectorとか)
自作型をこれに合わせるかは好みの域を出ない気がする
自分は型と関数で区別付けたいから PascalCaseにしてます (例. class MyData; enum MyEnum)
標準ライブラリは型が lower_snake なんだけどね
(std::string とか std::vectorとか)
自作型をこれに合わせるかは好みの域を出ない気がする
自分は型と関数で区別付けたいから PascalCaseにしてます (例. class MyData; enum MyEnum)
はちみつ先生の中の人ってエピステーメー氏じゃないですか。
エピ氏はかつて標準化委員だったそうです。はちみつ先生は、規格書が完全に頭に入ってる感じですから委員経験者と見ても違和感ない。
スレ民に委員がいるという話もあります。
あと前に「~じゃろ」ってレスを一度だけ見たのですが、それがエピ氏風に思えました。
なるほどー
証拠としては足りないと思うけども矛盾はしない
はちみつ氏と対立する立場で議論したことがあるけども
エピ氏だとしたら感慨深い
STL標準講座で勉強した世代だし
>>928 私は個人的なことは書かないようにしているし書いている場合でも嘘を混ぜているのだけれどプロのプログラマではないのは本当だと断言する。
肯定も否定もしたくないんだけど変に誰かと混同されるとその人に迷惑がかかるかもしれないからはっきりさせておく。
私はプログラムなりプログラミングの解説なりで金を貰ったことは全くない素人で、名の知られた人物ではない。
アマチュアなりになんらかの分野で有名だったりもしない。
>>930 規格が頭に入ってるわけないでしょ。 毎回調べてる。
プログラムの設計の妥当性などについては議論を戦わせればよいと思うけど今ある規格がどうなってるかは規格を調べるしかない。
それなのに空想で議論するような馬鹿馬鹿しいことがちょくちょく起こってるから話を先に進めたくて規格を持ち出してるだけ。
名前が抜けてた。
>>932 は私ね。
JaneXeno で書き込めなくてウェブブラウザから書き込んだらミスった。
質問です。参考書に乗ってた例試してたんですが下のコードがどういう動作してるのかよくわかりません。実行したらif(argc !=2)のところのコメント表示しかされませんでした。
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char *argv[])
{
if(argc !=2) {
cout <<"使い方: WRITE <ファイル名>\n";
return 1;
}
ofstream out(argv[1]);
if(!out) {
cout <<"出力ファイルが開けません\n";
return 1;
}
char str[80];
cout << "文字列をディスクに書き込み、$で停止します\n";
do {
cout << ": ";
cin >> str;
out << str << endl;
}while(*str !='$');
out.close();
return 0;
}
>>935 返信ありがとうございます。
mainのところがコマンドライン実行用のものだとわかったのですがif(argc !=2)だけが実行されて
char str[80]の一行下のコメントまで行かないで実行終わってるのでそこがどうなってるのかよくわかってません。
参考書に載ってるからまさかと思ったんですが
>>934のコードってif文のreturnで強制終了させられてるってことですよね?
ちょっと気になってif文のところコメントアウトして動かしてみたらdo while文のところまで動いてたからif(argc !=2)の説明文表示しておいてがreturn 1で返してmainのところが終了させてるのかというのであってますか?
しかも出力ファイル検出用のif文のところも絶対に入る形になっちゃってるみたいなので説明文はdo while文の入力で出力ファイル指定してね。みたいな文章ついているんですが例として出てるのに欠陥あるコードという認識でよろしいのでしょうか?
自己解決しました。
今回の例って実行時に一緒に書き込みファイル名入力するだけだったのを気付いてなかっただけでした。
せっかく
>>935がキーワードで検索してるのに「自己解決」かよ
超初心者スレでそんな回りくどい指摘で理解しろというほうが厳しいのでは
>>934 「よくわかりません」というのは質問になっていません。
何がわからないのかが伝わるようにまとめてください。
結果からすると argc や argv がコマンドラインから渡されるものだということがわかっていなかったようですが、質問一般のやり方としては「こうなると理解している」「でも実際にはこうなった」という形にすると伝わりやすいと思います。
質問を整理する過程で答えが分かってしまうのもよくあることです。 (ラバーダック・デバッグ)
それと参考書を元にしている場合は参考書のタイトルを書くのが望ましいです。
もしその本を持っている人がいたら前後の文脈からより適切な回答をできますし、同じ疑問をもった人がウェブ検索でここにたどり着くことが出来るかもしれないからです。
と、超初心者スレらしく質問の仕方の基本を書いておきます。
!=2のほうが安全よね
引数が2つ以上渡された場合、ユーザーが引数の意味を勘違いしている可能性があるので第1引数をファイル名として扱うのは危険かもしれない
まんこまんこー まんこまんこー まんこまんこー 君にまんこまんこー
すみません、std::atomic<bool> m_added = false; というインスタンス変数がある
クラスで bool isAdded() { return m_added; } というメンバ関数を作ると
error: use of deleted function 'std::atomic<bool>::atomic(const std::atomic<bool>&)'
というエラーになってしまいます。なぜこんなことに?
ググると return m_added.load(); とすればよさげで、実際エラーにはならなくなりますが
これで合っていますでしょうか?
>>947 それは std::atomic<bool> という型であって、bool型ではないから。
load()でboolに変換されているということだね。
>>947 インスタンス変数って何? 文脈から推測するとデータメンバのことかな?
だとするとこんな感じのことだと思って説明するよ。
class foo {
std::atomic<bool> m_added = false;
public:
bool isAdded() { return m_added; }
};
こういう書き方だと std::atomic<bool> m_added = false; はコピー初期化という扱いになる。
なのでコピーコンストラクタが必要だが std::atomic にはコピーコンストラクタが無いのでコピーコンストラクタがないという旨がエラーメッセージとして表示される。
解決方法としてはメンバ初期化子リストで初期化すればいい。 これなら直接初期化の扱いになる。
class foo {
std::atomic<bool> m_added;
public:
foo(void) : m_added(false) {}
bool isAdded() { return m_added.load(); }
};
C++17 以降だとコピー省略が保証される (かつコピーコンストラクタの存在を要求しない) 場面なので C++17 以降を使うのなら修正は必要ない。
std::atomic<T> には operator T() があるので std::atomic<bool> から bool へは変換できて、そのときの効果は std::atomic<bool>::load を呼び出すのと同じ。
暗黙に変換するのでこの部分は本来なら問題ないはず。
ここを修正してエラーが出なくなったというのは何か誤解してると思う。
すみません、色々勘違いやら説明不足やらあるようです。あと用語もいろいろと。
まず std::atomic<bool> m_added = false; という初期化ですが、
自分の環境はC++17(のはず)なので、これは大丈夫だったようです
で、本当の問題は、condition_variable::wait_for()の述語バージョンのコードでして
諸般の事情でネットから拾ってきたコードを一部変更して書きますと(たぶんインデントが
壊れますが、ご了承ください)
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <atomic>
std::mutex mtx;
std::condition_variable cv;
std::atomic<bool> ready = false;
void wait_for_event() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait_for(lock, std::chrono::seconds(3), []{ return ready; });
std::cout << "Event occurred or timeout reached" << std::endl;
}
int main(void) {
std::thread worker(wait_for_event);
worker.join();
return 0;
}
volatileが廃止されてatomicになったんだっけ?
この、述語部分のラムダ式で return ready; とするとコピーが発生するのでatomic的に
まずい(それをコピーコンストラクタをdeleteすることで実現している)、という理解です
で、ではどうしたらいいかという話に
うわ、名前の
>>949は間違いです、
>>947でした、ごめんなさい
>>951 ラムダ式の返却値の型は省略すると return に与えた式から推論され、推論結果は参照にはならない。
つまり []{ return ready; } は []->std::atomic<bool>{ return ready; } と書いたのと同じということ。
これだと値を返すときにコピーが発生するのでコピーコンストラクタが必要 (だけど実際には無い) ということになってしまう。
解決方法としては load を呼ぶというのは妥当な方法のひとつだけど、
返却値として bool を明示する、つまり []->bool { return ready; } とするのでもよいし、
キャストを書いて [] { return static_cast<bool>(ready); } というようにするのでも良い。
見栄えからすると [] { return bool(ready); } のほうが綺麗かな?
色々と書いたけど、この場合について言えば変換に頼るよりは load を呼んだほうが意図が読み取りやすくて良いと思う。
つーかこのコードだとreadyはatomicにする必要がない
>>947です。皆さんどうもありがとうございました
>>958 確かにそこは
実際、元のコードでも (
>>951はサンプルコードがベース)
他の部分は適宜mutexを使ってあり、atomicを使わなくてもいいような、あるいは逆に
mutexを使わずにatomicでいけるのかも、とか思ったりもしたのですが、
今回は最小限の変更で済ますことにしました
std::anyを使っていて、type()の返す形によって処理を変えたいのですが、
今はこれを typeid(形) と比較するif-else文の繰り返しを書いています
ググったら、hash_code()を使えばswitch文で書けるというのがあったのですが... 書けます?
エラーでコンパイルできないんですが
error: call to non-'constexpr' function 'std::size_t std::type_info::hash_code() const'
>>960 「使えば」というのはどう使うという状況を言ってる?
具体的なコードを出して。
>>960 switch の case ラベルに hash_code を使うという意味なら不可能。
case ラベルは定数 (定数式) であることを要求していて std::type_info::hash_code は constexpr が付いていないので結果は定数にならない。
コンパイル時計算するなんらかのハッシュ関数を用意すれば一応はなんとかならんでもないが……。
余興の類であって普通のテクニックとは言い難い。
そもそも std::any が不格好な仕組みなので std::any を使う以上は不格好になることを受け入れないと仕方がないと思う。
なに?プログラムって。むつかしそうだなー
ぜんぜん知らないんだけど、ちょっとやってみたいなー
ってな人も、入れてあげてね。
そういうスレなんだから。
そうしたければお前がやるんだよ
他人に期待すんな
こっちは気が向いたら好きに回答するだけ
あと過度な自治厨は嫌われるからな
人がいないからって、
お題を完全に無視して自分勝手
寄ってこようかとする何も知らない人は、
怖くて寄り付けないよ
独習でc++の勉強しているのですがそろそろ終わり見えて来たんで終わる前に次の参考書ほしいのですがどんなのがいいのでしょうか?
現在の作りたいソフトがチューナーボードを利用したチャンネルスキャンや復調前の搬送波の保存をwinやLinuxで使える規格で作ってみたいと思っています。最終的にはそこから番組表とか自動構築できるところまでやってタイムシフトできるようにしてみたいと思ってます。
基本わかったら作り始めたらいい
チューナーボードのsdkのマニュアル読め
最初は出来損ないでいいから完成させろ
lower_bound x以上で最小
upper_bound xより上で最小
upper_bound - 1 x以下で最大
は記述がありましたが
lower_bound - 1をググってるのですが出てきません
多分x未満で最大だと思うのですがあってますか?
>>967 sdkのマニュアルとかないボードみたいなんでテレビ視聴用のテストソフトコード見ながら自分が欲しいもの書いてみます。
ところでvisual studio使ったことないのでわからないのですがこのソフトの書き方、読み方しっかり学べる本ってないでしょうか?今までテキストエディタで書いてg++でやってたからビルドとテストがあるぐらいしかわかりません。
>>971 マイクロソフトのサイトを見ながら学習するのがよいと思う。
細かな部分はバージョンによっても変わるし、本を買ってもすぐ時代遅れになるから。
lud20250214054150このスレへの固定リンク: http://5chb.net/r/tech/1542002113/
ヒント:5chスレのurlに http://xxxx.5chb.net/xxxx のようにbを入れるだけでここでスレ保存、閲覧できます。
TOPへ TOPへ
全掲示板一覧 この掲示板へ 人気スレ |
Youtube 動画
>50
>100
>200
>300
>500
>1000枚
新着画像
↓「0からの、超初心者C++相談室 」を見た人も見ています:
・結婚相談所ってどうなん?行ったことあるやついる?
・【ネ実】料金爆上げ!水道法改正で民営化決定!これからは一軒一戸、井戸の時代!
・虐待死児童の実母のDV被害は18.9%、地域社会から孤立…厚労省専門委が初調査 [蚤の市★]
・高知県「すまん、早明浦ダム先月から満タンやねん。貯水量確保するために毎秒600トンの放流開始するわ。下流の県は気ぃつけてなw」
・【新型コロナ】愛知・岡崎で80代男性が死亡、死後の検査で判明 11日NYから帰国 県内144人目・死亡17人
・【社会】ゴルスタ個人情報流出問題 運営会社スプリックスでは数年前から「みせしめ」存在 関係者に聞いた
・必殺からくり人
・【改】あなたの嫌いな人から連想する単語・特徴
・この板の意味がわからん
・千葉大から東大院
・合気から派生する剣術
・2016年からの軌跡
・明日から無職なんだが
・高専からの編入66th
・安倍、国会から逃亡
・昼寝から目覚めた
・地獄からの絵スレ
・明日からやる気出す
・暇だから話そうよ
・4月からの和田さこ
・からあげセンター
・女が社会に出て来たから
・異世界から来たんだが
・50歳からの孤独 5
・作曲したから聴いてくれ
・愛国から幸福ゆき
・今からあぶり出しを行う
・やっぱり女は40歳から2
・だから何?って書き込み
・特定派遣からの転職
・蒲郡競艇は駅から近い?
・端末変えたから確認
・今からこれを食う
・東京 これから豪雨
・からあげの日記 Part91
・18歳処女からのメール
・26歳から大学へ進学
・少額だから貸すよ
・欅坂46から国民を守る党
・VIPからき☆すた
・暇だからお話しよ
・朝から酒飲んでる
・(´・ω・`) わからん……
・四時だから4回だした。
・○年後から来ました
・岡田斗司夫から学ぶこと
・NGTは新潟から出ていけ
・悪役は日銀から財務省へ
・酒の味が分からない
・50歳からの孤独 25
・きみたちから感じる
・岡田有希子自殺から34年
・60代から見る加藤純一
・なんJから来ました
・在日から国民を護る党
・浮気ってどこから?
・日本は狭いんだから
・絵を描いてみたから見て
・新参にはわからないこと
・口の奥からドブの臭い
・お米おいしいからさ
・なんjから来たンゴ
・今から同志社目指す
・就職活動するべからず!
・なんJからきたンゴ
・灘、筑駒から一橋。
21:29:36 up 31 days, 22:33, 1 user, load average: 41.80, 68.67, 78.11
in 0.047163009643555 sec
@0.047163009643555@0b7 on 021411
|