まだ書きかけ。
モチベーション維持のために公開
GitHub Pagesでの閲覧
https://ezoeryou.github.io/cpp-intro/
GPLv3
Beginner's guide for C++
License: Other
まだ書きかけ。
モチベーション維持のために公開
GitHub Pagesでの閲覧
https://ezoeryou.github.io/cpp-intro/
GPLv3
022 で switch-case 文が使用されていますが、switch-case 文の説明がありません。
どこかで説明すべきだと思います。
この文書はまだ書きかけということなので、このような指摘をしてもよいのか迷うのですが、報告します。
所有するクラス
にown型のコード例がありますが、
https://github.com/EzoeRyou/cpp-intro/blame/ad6fd59055d969a70aa7b59d279a225df79551e7/035-copy.md#L306-L320
このコード例はこの下にあるown型の変換コンストラクタのコード
https://github.com/EzoeRyou/cpp-intro/blame/ad6fd59055d969a70aa7b59d279a225df79551e7/035-copy.md#L427-L439
でエラーになってしまうようです。
メンバ関数getにconstがついていないために、constがついた&rからgetが呼び出せずエラーになっているようです。
19章の
コンストラクターはクラスが初期化されるときに実行される。例えば以下のプログラムを実行すると、
int main() { S a(1) ; S b(2) ; S c(3) ; }以下のように出力される。
123
の部分について,クラスS
とそのコンストラクタの定義が抜けているように思います。
#include "../all.h"
void f(const int &){
std::cout << "lvalue\n";
}
void f(const int &&){
std::cout << "rvalue\n";
}
int main(){
int object {};
f(object);
f(object + object);
f([&]{ return object; }());
f(std::move(object));
}
$ g++ -std=c++17 -Wall lvalue-and-rvalue.cpp
lvalue-and-rvalue.cpp: In lambda function:
lvalue-and-rvalue.cpp:15:16: error: ‘object’ is not captured
15 | f([]{ return object; }());
| ^~~~~~
lvalue-and-rvalue.cpp:15:6: note: the lambda has no capture-default
15 | f([]{ return object; }());
| ^
lvalue-and-rvalue.cpp:11:7: note: ‘int object’ declared here
11 | int object {};
| ^~~~~~
https://twitter.com/TartanLlama/status/1283816537778982914 を思い出した。
試しに object
を constexpr
にしたらコンパイルされた。
「解放」か「開放」かどちらかに統一すべきだと思います。
▪数字
s/一回/1回/g
s/一行/1行/g
s/二行/2行/g
s/2つめ/2つ目/g
s/2番め/2番目/g
s/二通り/2通り/g
s/三種類/3種類/g
s/二箇所/2箇所/g
s/二度/2度/g
s/一ヶ月/1ヶ月/g
s/一週間/1週間/g
▪あ
(〜と)s/言う/いう/g
s/一体/いったい/g
s/予め/あらかじめ/g
s/一番/いちばん/g
s/後/あと/g
s/あがる/上がる/g
s/いちど/一度/g
s/あやまり/誤り/g
s/嬉しい/うれしい/g
s/いれる/入れる/g
s/おこる/起こる/g
s/一切/いっさい/g
s/諦め/あきらめ/g
s/色々な/いろいろな/g
s/当たる/あたる/g
s/今/いま/g
s/今更/いまさら/g
s/おなじ/同じ/g
s/未だ/いまだ/g
s/覚えてる/覚えている/g
▪か
s/頃/ころ/g
s/かわり/代わり/g
s/気づく/気付く/g
s/気がつく/気が付く/g
s/かけ合わせる/掛け合わせる/g
s/ことなる/異なる/g
s/結局/けっきょく/g
s/きわめて/極めて/g
s/かわる/変わる/g
s/かねる/兼ねる/g
s/聞きなれない/聞き慣れない/g
s/かける/掛ける/g
s/かく/書く/g
s/かえす/返す/g
s/くる/来る/g
(教えを)s/乞う/請う/g
▪さ
s/様々/さまざま/g
s/先程|さきほど/先ほど/g
s/全て/すべて/g
s/すこし/少し/g
s/早速/さっそく/g
s/更に/さらに/g
s/揃える/そろえる/g
s/すむ/済む/g
s/すばらしい/素晴らしい/g
(〜)s/してる/している/g
s/凄い/すごい/g
s/知れない/しれない/g
s/全然/ぜんぜん/g
▪た
s/つける/付ける/g
(名前が)s/つく/付く/g
(期待|文字|順番)s/通り/どおり/g
(以下の)s/通り/とおり/g
s/ディレクトリ/ディレクトリー/g
s/大変/たいへん/g
s/ためし/試し/g
s/共に/ともに/g
s/つかう/使う/g
(警告が)s/でる/出る/g
s/時/とき/g
s/たばねる/束ねる/g
(引数を)s/とる/取る/g
s/つくる/作る/g
s/たしかに/確かに/g
s/使いまわす/使い回す/g
s/大抵/たいてい/g
s/囚われる/とらわれる/g
s/取りうる/取り得る/g
▪な
s/なれる/慣れる/g
s/無し/なし/g
s/無い/ない/g
s/何故/なぜ/g
s/なりたつ/成り立つ/g
s/中/なか/g
s/なんだろう/何だろう/g
s/なんの/何の/g
s/のこり/残り/g
▪は
s/一つ|ひとつ/1つ/g
s/ふたつ/2つ/g
(〜の)s/ほう/方/g
x s/ほか/他/g
s/一通り/ひと通り/g
s/一休み/ひと休み/g
s/欲しい/ほしい/g
s/はじめ/始め/g
s/甚だ/はなはだ/g
s/剥がす/剝がす/g
s/殆ど/ほとんど/g
▪ま
s/むだ/無駄/g
s/まて/待て/g
s/もつ/持つ/g
s/むずかしい/難しい/g
s/全く/まったく/g
s/メモリ/メモリー/g
s/みなれない/見慣れない/g
s/もとに/元に/
s/元々/もともと/g
s/見えてる/見えている/g
▪や
s/良し悪し/善しあし/g
s/良く/よく/g
(すれば)s/良い/よい/g
s/よぶ/呼ぶ/g
s/呼びだし/呼び出し/g
s/易い/やすい/g
▪ら
s/ライブラリー/ライブラリ/g
▪わ
s/わかれる/分かれる/g
s/別れる/分かれる/g
s/分かる/わかる/g
s/罠/わな/g
▪欧文
s/GNU make/GNU Make/g
▪人名
s/エドガー・ダイクストラ(Edsger Wybe Dijkstra)//g
本文では、non_ofの実装として
{
for ( auto iter = first ; first != last ; ++iter )
{
if ( pred(*iter) )
return false ;
}
return true ;
} ;
とありますが、for文の終了条件は
iter != last
ではないでしょうか。
033-vector-implementation.md内でconstexprについて
constexpr
というキーワードがあるが、ここでは気にする必要はない。あとで学ぶ。
となっていますが、後ろの部分を見ても十分な説明がないように思います。
その後もコード例などにconstexprは出てくるため、説明を追加してほしいです
012-floating-point.mdのNaN(Not a Number)の節で、
// false
bool d = NaN != NaN ;
とあります(コードから抜粋)。しかし、このサイトの例でgcc 11.1(C++20)を選び、
std::cout << "NaN != NaN? " << std::boolalpha
<< ( std::numeric_limits::quiet_NaN()
!= std::numeric_limits::quiet_NaN() ) << '\n';
を追記し、実行するとtrueになりました。
NaN != NaN はtrueではないでしょうか?
5章 https://github.com/EzoeRyou/cpp-intro/blob/master/005-the-restaurant-at-the-end-of-the-branch.md の、論理否定の説明のところでうまく理解ができず質問させていただきたく issue を立てさせていただきました。
以下の部分で「ロケットが発射可能なときに実行される」というコメントがあるのですが、コードは「ロケットが発射可能ではないときに実行される」ように読めます。ただ、そうすると一つ前の例と is_rocket_ready_to_launch()
の中以外は同じになってしまいますし、実行される内容も発射可能ではないはずなのに、発射シーケンスに入ってしまうように読めます。
int main()
{
// ロケットが発射可能なときに実行される
if ( !is_rocket_ready_to_launch() )
{ // カウントダウン
std::cout << "3...2...1...Hallelujah!\n"s ;
}
}
本文の説明の方も、
論理否定演算子を使うと、
false
のときのみ実行されてほしい条件分岐が書きやすくなる。
同じように、true
のときに実行されてほしくない条件分岐も書ける。
と2つの例が同じ条件について例示をしているように読めてしまい、この2つでどういう違いがあるのかわからず、間違いであるのか私の理解が追いついていないのかわからず困っております。
バージョン: commit a23c2c3 及び 書籍版の初版
「22章 配列」のint型5要素の配列のストレージの図が、文章ではintが4byteの環境での話としているのに、図では1要素2byteとなっていて、末尾の(0~4番目の内の)4番目の要素が20byteのストレージのちょうど真ん中に来てしまっています。
顧客が本当に必要な図は、1要素4byteとして、末尾の4番目の要素が20byteのストレージのちょうど最後に来る図でしょうか。
// ムーブ
Integer( Integer && r )
: ptr( r.ptr )
{ r.ptr = nullptr ; }
Integer operator =( Integer && r )
{
delete ptr ;
ptr = r.ptr ;
r.ptr = nullptr ;
return *this ;
}
上記のコードが掲載されていますが、上記実装だと自身のコピーを返してしまいます。
正しくは Integer & operator =( Integer && r )
ではないでしょうか?
036 の2文目、
「コピーが値をコピー(複製)するのに対し、ムーブは値を(移動)させる。」
は言っていることが重複しているように思います。
「コピーが値を複製するのに対し、ムーブは値を移動させる。」
としたらどうでしょうか。
以下のC++のソースファイルは標準出力にhelloと出力するものだ。
#include <iostream>
int main()
{
std::cout << "hello" ;
}
とあるが、ここでstd::coutはflushされていないように思います。このとき標準出力に確実に書き出された保証はあるのでしょうか?
C++初心者なので間違っているかもしれませんが、009-vectorの章を実践している時、
std::vector
を使用するために
#include <vector>
をする必要があることに気付かず悩まされました。
これからの章も未確認なのですが明示的に表記があるとわかりやすいと思います。
031, 033-035. で xxx_traits という名前が複数出てきますが、traitsとは何かという説明が欲しいです。
008-loop.md の一番最後の factorial 関数の例ですが、
このコードは末尾再帰になっている。
とありますが、なってないように見えます。
私の知ってる末尾再帰は次のようなものです。
int factorial(int n, int acc=1) {
if (n <= 1) {
return acc;
} else {
return factorial(n - 1, n * acc);
}
}
// =>
int factorial_loop(int n) {
int acc = 1;
while (true) {
if (n <= 1) {
return acc;
}
acc *= n;
n--;
}
}
016-algorithm.md に copyアルゴリズムの説明で、「これは実質的に以下のような操作をしたのと等しい。」とありますが、sourceとdestinationの内容が同じになっていることがわかりません。代入かなにかが抜けているのではないでしょうか?
int main()
{
std::vector<int> source = {1,2,3,4,5} ;
std::vector<int> destination(5) ;
}
例えば、以下のようであれば同じとわかります。
int main()
{
std::vector<int> source = {1,2,3,4,5} ;
std::vector<int> destination= {1,2,3,4,5} ;
}
( close となった issue の reopen はできなかったので、つづきを別 issue としています。)
#3 (comment) より:
...昔のC言語では0はnullポインターの値だと規格上定められてはいなかった。
「規格」としておそらく最古の C89 時点でも 0
はヌルポインタ定数とされています。
http://port70.net/~nsz/c/c89/c89-draft.html#3.2.2.3
An integral constant expression with the value 0, or such an
expression cast to type void * , is called a null pointer constant. ...
同様の規定が C99, C11 のドラフトでも確認できます。
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
ということで以下の点を改めて見直しおねがいします。
c250d15#diff-d27600081f0d6802e8fd7ede213346bfR230
C++ではさらに歴史的な理由で、
0
もnullポインター値として扱う。ポインタの文脈で
0
をnullポインター値として扱う(ヌルポインタ定数と
する)のはC言語も同じなので、「C++では」として直前のNULL
の紹介と
分けられているのは不適切だと思います。
修正 50afb5a 後の文面について。
...わからない値を持ったポインターの参照先への読み書きは未定義の挙動を引き起こす。
実際は参照先への読み書き以前に(直前の int の例と同様に)未初期化変数の
値を読んだ時点で未定義動作となります。参照先の読み書きを行わない
std::cout << pointer
でも未定義動作ということです。
後続の「なぜ未定義の挙動になるかというと~」も含めて、この記述だと
「読み書きさえしなければ未定義動作とならない」と読まれる可能性があり、
適切ではないと思います。
「意味上のポインター」(028-pointer-semantics.md) の説明に不適切と思われる箇所が
あったのでお知らせです。
・・・「まだ書きかけ」として公開されている状態なのでこういった指摘が
歓迎されるものか不安に思いながら書いてます。煩わしいようならそこらへんの
ポリシーなどを教えてもらうだけで閉じてもらってもかまわないです。
(指摘が歓迎されるのなら他のところも見たりしようかな、とも思ってます。)
c250d15#diff-d27600081f0d6802e8fd7ede213346bfR169
わからない値の整数を読むことは推奨できない。書くことはできる。
未初期化の int 型変数の値(不定値)を読むことは「推奨できない」とされた
うえで、未初期化のポインタ型変数の値(不定値)をデリファレンスした場合を
「未定義の挙動」であると説明されていますが、実際は int の不定値となる
式を評価した場合の挙動も未定義なので不適切な対比になっていると思います。
参照: https://timsong-cpp.github.io/cppwp/n4659/dcl.init#12
... If an indeterminate value is produced by an evaluation, the
behavior is undefined except in the following cases:
- If an indeterminate value of unsigned narrow character type or
std::byte type ...
c250d15#diff-d27600081f0d6802e8fd7ede213346bfR230
C++ではさらに歴史的な理由で、
0
もnullポインター値として扱う。
ポインタの文脈で 0
をnullポインター値として扱う(ヌルポインタ定数と
する)のはC言語も同じなので、「C++では」として直前の NULL
の紹介と
分けられているのは不適切だと思います。
「イテレーターと添字の範囲」のところで「実はC++に限らず、現在使われているすべてのプログラミングはインデックスを0から始めている。かつてはインデックスを1から始める言語も存在したが、そのような言語はいまは使われていない。」とあります。
しかし、Lua 言語はインデックスが1から始まります。まだそれなりに使われています。
正確には、Luaではデータを構造化する仕組みとしてテーブル(table)だけがあり、テーブルは基本的には連想配列です。
しかし、キーとして 1と連続する整数値を指定した時は、配列のインデックスとして特別扱いされます。
たとえば、
https://wandbox.org/permlink/BU6dtlbYTTaQlwe9
ですので、存在しないは言い過ぎかと思います。
16.6節のsearch中の例のコードをコンパイルすると,no viable conversion error となります.
std::searchの動作は(文中の記法のもと)
「要素の並びがイテレーター[first1, last1)の範囲に存在すれば,
最初に一致する並びの先頭のイテレータを返し,そうでない場合はlast1を返す」
ではないでしょうか.
"033-vector-implementation"に関してです。
std::string * s = traits::construct( a, p, "hello") ;
と、traits::constructの戻り値を定義していますが、c++ referenceを見るとtraits::constructの戻り値はvoidですし、std::string *s
と定義する必要はないのではないでしょうか?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.