リテラル
C++でのリテラルは基本的にC言語でのリテラルと同じですが、少しだけ追加されているものがあります。
ブーリアンリテラル
ブーリアンリテラル(boolean literal)はtrue
とfalse
の二種類が存在し、それぞれ「真」と「偽」を表わします。
これらはif文などの条件判定に使用されます。
ブーリアンリテラルはbool型の変数に格納できます。
bool型はC言語にはなく、C++に新しく追加されたデータ型です。
(C言語でも専用のライブラリを使用することでbool型相当の機能を使用することは可能です)
bool b1 = true;
bool b2 = false;
if(b1) { /* 実行される */ }
if(b2) { /* 実行されない */ }
ブーリアンリテラルは整数型に変換することができ、true
は1
に、false
は0
に変換されます。
他のデータ型からbool型への変換は、条件式で真となるものはtrue
、偽となるものはfalse
に変換されます。
int n1 = true; //1
int n2 = false; //0
bool b;
b = 1; //true
b = -1; //true
b = 12.3; //true
b = 0; //false
b = 0.0; //false
b = "ABC"; //true
b = ""; //true
b = NULL; //false
b = (bool)nullptr; //false
nullptrリテラル
nullptr
はNULLポインタを表すリテラルです。
(pointer literal)
C言語では、NULLポインタはNULL
マクロ(定数NULL)を使用するか、単に数値の0を使用していました。
NULLマクロはstdio.h
などに定義があり、実体は数値の0
や((void*)0)
です。
C++にもiostream
などのヘッダーファイルにNULLマクロが定義されていますが、C++においてNULLマクロの使用は細かい点で不都合があるため、NULLポインタを表す場合はnullptr
の使用が推奨されます。
C++ではデータ型の変換がC言語よりも厳格になっていて、void*
型を他のポインタ型に暗黙的に変換できません。
NULLマクロを使用する場合にわざわざキャストしなければならないのは手間なので、C++のNULLマクロは0
で定義されています。
#define NULL ((void*)0)
//エラー
int* p1 = NULL;
//OK
int* p2 = (int*)NULL;
//OK
int* p3 = 0;
しかし、NULLマクロが0でであることによりまた別の問題が起こります。
#define NULL 0
//int型版
void func(int x) {}
//void*型版
void func(void* x) {}
int main()
{
//int型版が呼び出される
func(NULL);
//void*型版が呼び出される
func((void*)NULL);
//void*型版が呼び出される
func(nullptr);
}
C++では関数のオーバーロードにより、引数の異なる関数を複数定義できます。
上記のコードのように引数に数値とvoid*
型を取る関数のオーバーロードがある場合、NULL(数値の0)を指定すると数値のほうの関数が呼び出されてしまいます。
二番目のようにキャストすればvoid*
型版を呼び出せますが、記述が面倒ですし、なにより「NULL」なのにNULLポインタを示さないのはわかりにくいコードとなります。
NULLポインタにはnullptr
を使用すればこのような問題は起こりません。
生文字列リテラル
文字列リテラルの先頭にR
をつけ、文字列を丸括弧で囲うと生文字列リテラルという機能が使用できます。
生文字列リテラルはエスケープ処理が必要な文字をそのまま記述することができます。
const char* s1 = R"(This is a "pen")";
const char* s2 = R"(C:\Program Files)";
std::cout << s1 << std::endl;
std::cout << s2 << std::endl;
This is a "pen" C:\Program Files
生文字列リテラル中ではコード上の文字列が「そのまま」出力されます。
(後述する例外はあります)
コード上の改行も改行文字(\n
)として扱われます。
const char* s = R"(
ABCD
EFGH
)";
std::cout << s << std::endl;
ABCD EFGH
ただし)"
という文字列は生文字列リテラルの終了の書式と同じであるため、そのまま記述することはできません。
これを記述する場合は開始括弧の前に目印となる文字列を指定し、閉じ括弧の直後に同じ目印を記述します。
const char* s = R"...(ABCD"(EFGH)")...";
上記の例では...
という文字列を使用しています。
目印に使用する文字列は自由です。
(同じ種類の文字である必要はありません)
std::stringリテラル
C++14から、文字列リテラルの末尾にs
サフィックスを付加することでstd::string
型(basic_string
型)のオブジェクトを直接作成することができます。
#include <iostream>
#include <string>
int main()
{
using namespace std::string_literals;
//以下の二つは同じ型
std::string a = "abc"s;
auto b = "abc"s;
//C++20
std::u8string c = u8"abc"s; //UTF-8
//C++14~C++17
std::string d = u8"abc"s; //UTF-8
std::u16string e = u"abc"s; //UTF-16
std::u32string f = U"abc"s; //UTF-32
}
std::string
リテラルはstd::string_literals
名前空間(std::literals::string_literals
名前空間)のusingディレクティブが必要です。