目的
競技プログラミングに入門するにあたり、C++の使い方を備忘録として残す。
1. 文法
この節では、C++の文法について説明する。2020年10月17日時点で、下記のサイトを参考にC++の基礎的な事項を理解を深めている。C++の文法に関する情報整理が完了後に記載することとした。
- 苦しんで覚えるC言語
- C/C++概要
- C++
つまづいたポイントのみ情報を整理して理解を深める。
- 参照とポインタの違い 2020年10月時点
- C++の実行方法 2020年10月時点
1.1 ポインタについて
この節では、ポインタの基礎事項について説明する。
ポインタはメモリ上の位置を示すものです。
1.2 参照について
この節では、参照の基礎事項について説明する。
参照はオブジェクトそのものを指定する。以下のソースコードをもとに説明する。
#include <iostream>
int main()
{
int num = 10;
//numを参照する。
//参照は&を付けて宣言する変数refで定義する。
//ここで、アドレス演算子は&である。
int &ref = num;
//参照を通してnumを書き換えてみる。
ref = 20;
// 参照を通してnumを書き換えれたか確認する。
// 参照によりnumが10ではなく20と表示される。
std::cout << num << std::endl;
std::cin.get()
}
1.3 参照とポインタの違いについて
この節では、参照とポインタの違いについて説明する。
参照はオブジェクトそのものを指定する。オブジェクト以外を指すことや再度オブジェクトを代入することはできず、実行時エラーとなる。下記にポインタと参照の性質について箇条書きではあるがまとめる。
-
ポインタ*p
- メモリ上の位置を示すものである。
- ポインタが指す先に必ずしもデータが存在することは保証しない。
- 宣言時に初期化しなければ不定である。
-
参照&r
- 必ずオブジェクトを指していることが求められる。
上記のポインタと参照の性質の差異を表に示す。
項目 | 参照&r | ポインタ*p |
---|---|---|
ポインタ変数に意味のないアドレスを渡す。 | × | 〇 |
NULLポインタといった何も指していないポインタを作成する。 | × | 〇 |
意味のないアドレスを指す | × | 〇 |
//ポインタでできること。
int *p1;
int *p2 = NULL;
int *p3 = (int*)1;
//ポインタでできるが、参照ではできないこと。
//参照
//いずれもエラー
int &r1;
int &r2 = NULL;
int &r3 = (int&)1;
1.4 引数による参照渡し
この節では、関数の引数で参照を用いる参照渡しについて説明する。
補足ではあるが、ポインタと参照の構造体変数のメンバ変数へのアクセス方法の違いについて説明する。
- ポインタ
- 構造体のメンバ変数へのアクセスはアロー演算子(->)を用いる。
- 参照
- 構造体のメンバ変数へのアクセスはドット演算子(.)を用いる。
1.4.1 引数が構造体の場合
引数が構造体であるときの参照渡しについて説明する。
#inculde <iostream>
#define NAME_LENGTH 50
//列挙型のGenderの宣言
enum Gender
{
MALE,
FEMALE
};
//構造体Personの宣言
//メンバ変数はname, age, genderで構成される。
struct Person
{
char name[NAME_LENGTH];
int age;
enum Gender gender;
};
//関数のプロトタイプ宣言
//省略はできるが必ずC++では宣言する。
void showPerson(Person[], int);
void showPerson(Person&);
//今回は関数showPersonをオーバーロードする。
//明示的に引数の型を宣言しなくても、どちらの関数を使用するか自動的に判断し呼び出す。
//補足情報
//関数の処理が同じで、引数のデータ型が異なるだけであれば関数テンプレートという機能を用いる。
// 処理内容
// コメントを簡素化するため、showPerson(Person[], int)をA、showPerson(Person&)をA1とする。
// Aが構造体personを引数で受け取る。AがA1を呼び出す。
// A1の引数に参照渡しをしているので、AはA1を通して構造体personのメンバにアクセスする事が出来る。
// A1の引数に参照渡しをすることで、簡潔に構造体へのアクセスを記述することができる。
void showPerson(Person p [], int len)
{
for (int i = 0;, i < len; i++)
{
showPerson(p[i]);//ポインタではなく配列のインデックスを指定して引数に代入する!
std::cout << std::endl;
}
}
//引数は参照渡しで記述する。
void showPerson(Person &p)
{
using std::cout;
using std::endl;
cout << "name:" << p.name << "\n";
cout << "age:" << p.age << "\n";
if (p.gender == MALE)
cout << "gender:男" << endl;
else
cout << "gender:女" << endl;
}
int main()
{
person person[] = {
{"学生",20,MALE}
{"主婦",20,FEMALE}
};
// sizeofでメモリのサイズを読み込む。Nは、配列の要素数をメモリのサイズから算出する。
int N;
N = sizeof(person) / sizeof(person[0]);
showPerson(person, N);
std::cin.get();
};
2. C++の実行方法
この節では、C++を実行する方法について説明する。
C++を実行するには下記の手順を踏む。
- テキストファイルであるソースコードをコンパイルしてオブジェクトファイルを生成する。
- オブジェクトファイルと必要なライブラリをリンクして実行ファイルを生成する。
- 実行ファイルを実行する。
下記の節で、環境構築方法およびC++の実行方法について詳細に説明する。
2.1 環境構築[Windows]
この節では、Windows環境で実際にC++を実行する方法について説明する。
WindowsのVisual Studio Codeでの実行環境は下記のサイトをもとに構築する事が出来る。
Visual Studio Codeにおける環境構築
2.2 実行方法[Windows]
下記の手順を踏んで実行する必要がある。
Step 1. g++コマンドを用いて、cppファイルから実行ファイルを生成する。
# C言語のみの場合
gcc -o 実行ファイル名 C++ファイル名.cpp
#C++言語も使用している場合
g++ -o 実行ファイル名 C++ファイル名.cpp
Step 2. 生成された実行ファイルを実行する。
実行ファイル名.exe
2.3 複数ファイル
複数のソースコードから実行ファイルを生成する。ソースコードをコンパイルしオブジェクトファイルを生成する。複数のオブジェクトファイルをリンクし実行ファイルを生成する。
gcc -g -o main.o main.c
gcc -g -o sub.o sub.c
gcc -g -o func.o func.c
gcc -g -o program main.o sub.o func.o
$ make program
CC=gcc
CFLAG=-g
OBJGROUP=main.o sub.o func.o
all: program
program: $(OBJGROUP)
(ここはタブです)$(CC) -o program $(OBJGROUP)
コンパイル済みのオブジェクトの集合体をライブラリという。ライブラリには共有ライブラリと静的ライブラリがある。オブジェクトファイルをarコマンドでアーカイブしたもので、拡張子は.aである。ライブラリとリンク詳細はC++から話が逸れるのでURLを参照すること。
ライブラリ | リンク |
---|---|
共有ライブラリ/DLL | 動的リンク |
静的ライブラリ | 静的リンク |