Namespaces
Variants

Pointer declaration

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

ポインタまたはメンバへのポインタ型の変数を宣言します。

目次

構文

ポインタ宣言は、 宣言子 が以下の形式を持つ任意の単純宣言です。

* attr  (オプション) cv  (オプション) declarator (1)
nested-name-specifier * attr  (オプション) cv  (オプション) declarator (2)
1) ポインタ宣言子 : 宣言 S * D ; D 宣言指定子シーケンス S によって決定される型へのポインタとして宣言する。
2) メンバへのポインタ宣言子 : 宣言 S C :: * D ; D C の非静的メンバへのポインタとして宣言し、その型は宣言指定子シーケンス S によって決定される。
nested-name-specifier - 名前とスコープ解決演算子 のシーケンス ::
attr - (C++11以降) 属性 のリスト
cv - 宣言されているポインタに適用されるconst/volatile修飾(指し示される型の修飾は宣言指定子シーケンスの一部であり、これには含まれない)
declarator - 任意の 宣言子

ポインタから 参照 へのポインタは存在せず、 ビットフィールド へのポインタも存在しません。 通常、特に明記されていない場合の「ポインタ」という言及には、(非静的)メンバへのポインタは含まれません。

ポインタ

ポインタ型のすべての値は、以下のいずれかです:

  • オブジェクトまたは関数への ポインタ (この場合、ポインタはそのオブジェクトまたは関数を 指す と言います)、または
  • オブジェクトの終端を超える ポインタ 、または
  • その型の ヌルポインタ値 、または
  • 無効なポインタ値

オブジェクトを指すポインタは、 そのオブジェクトがメモリ上で占有する最初のバイトのアドレス を表します。オブジェクトの終端を過ぎたポインタは、 そのオブジェクトが占有するストレージの終端後の最初のバイトのアドレス を表します。

同じアドレスを表す2つのポインタであっても、異なる値を持つ可能性があることに注意してください。

struct C
{
    int x, y;
} c;
int* px = &c.x;   // pxの値は「c.xへのポインタ」
int* pxe= px + 1; // pxeの値は「c.xの終端を過ぎたポインタ」
int* py = &c.y;   // pyの値は「c.yへのポインタ」
assert(pxe == py); // == は2つのポインタが同じアドレスを表すかテストする
                   // アサーションが発生する場合としない場合がある
*pxe = 1; // アサーションが発生しなくても未定義動作

無効なポインタ値を通じた間接参照および無効なポインタ値を解放関数に渡すことは未定義動作を引き起こします。無効なポインタ値のその他の使用は処理系定義の動作となります。一部の実装では、無効なポインタ値のコピーがシステム生成のランタイムフォルトを引き起こすと定義する場合があります。

オブジェクトへのポインタ

オブジェクトへのポインタは、オブジェクト型の任意の式(他のポインタ型を含む)に アドレス演算子 を適用した戻り値で初期化できます:

int n;
int* np = &n;          // intへのポインタ
int* const* npp = &np; // 非const intへのconstポインタへの非constポインタ
int a[2];
int (*ap)[2] = &a;     // int配列へのポインタ
struct S { int n; };
S s = {1};
int* sp = &s.n;        // sのメンバであるintへのポインタ

ポインタは組み込みの間接参照演算子(単項 operator * )のオペランドとして現れ、これが指し示すオブジェクトを特定する lvalue式 を返します:

int n;
int* p = &n;     // nへのポインタ
int& r = *p;     // 参照はnを識別するlvalue式に束縛される
r = 7;           // nにint値7を格納
std::cout << *p; // lvalueからrvalueへの暗黙変換によりnから値を読み取る

クラスオブジェクトへのポインタは、メンバアクセス演算子 operator-> および operator->* の左辺オペランドとしても使用できます。

配列からポインタへの 暗黙変換 により、配列の最初の要素へのポインタは配列型の式で初期化できます:

int a[2];
int* p1 = a; // 配列aの最初の要素a[0](int型)へのポインタ
int b[6][3][8];
int (*p2)[3][8] = b; // 配列bの最初の要素b[0]へのポインタ、
                     // これは8個のintの配列3個からなる配列

ポインタに対する derived-to-base 暗黙変換のため、基底クラスへのポインタは派生クラスのアドレスで初期化できます:

struct Base {};
struct Derived : Base {};
Derived d;
Base* p = &d;

Derived ポリモーフィック である場合、そのようなポインタは 仮想関数呼び出し を行うために使用されることがあります。

特定の 加算、減算 インクリメント、デクリメント 演算子は配列要素へのポインタに対して定義されています:このようなポインタは LegacyRandomAccessIterator 要件を満たし、C++ライブラリの アルゴリズム が生配列を扱うことを可能にします。

比較演算子 は、いくつかの状況においてオブジェクトへのポインタに対して定義されています:同じアドレスを表す2つのポインタは等しいと比較され、2つのヌルポインタ値は等しいと比較され、同じ配列の要素へのポインタはそれらの要素の配列インデックスと同じように比較され、同じ メンバーアクセス を持つ非静的データメンバーへのポインタは、それらのメンバーの宣言順に比較されます。

多くの実装では、ランダムな起源のポインタの 厳密な全順序付け も提供されています(例えば、連続した仮想アドレス空間内のアドレスとして実装されている場合)。これを提供しない実装(例えば、ポインタの全ビットがメモリアドレスの一部ではなく比較時に無視する必要がある場合、追加の計算が必要な場合、あるいはポインタと整数が1対1の関係にない場合など)では、その保証を持つポインタ用の std::less の特殊化を提供しています。これにより、ランダムな起源のすべてのポインタを std::set std::map のような標準の連想コンテナのキーとして使用することが可能になります。

voidへのポインタ void

任意の型へのオブジェクトポインタは、 暗黙的に変換 可能です(場合によっては cv修飾 された) void ポインタへ。ポインタ値は変更されません。逆変換には static_cast または 明示的キャスト が必要であり、元のポインタ値を返します:

int n = 1;
int* p1 = &n;
void* pv = p1;
int* p2 = static_cast<int*>(pv);
std::cout << *p2 << '\n'; // 1を出力

元のポインタが何らかのポリモーフィック型のオブジェクト内の基底クラスのサブオブジェクトを指している場合、 dynamic_cast を使用して、最も派生した型の完全なオブジェクトを指す void * を取得することができます。

void へのポインタは、 char へのポインタと同じサイズ、表現、アラインメントを持ちます。

voidへのポインタは、未知の型のオブジェクトを渡すために使用され、これはCインターフェースで一般的です: void std::malloc void * を返し、 std::qsort は2つの const void * 引数を受け入れるユーザー提供のコールバックを期待します。 pthread_create void * を受け入れ、返すユーザー提供のコールバックを期待します。すべての場合において、使用前にポインタを正しい型にキャストするのは呼び出し側の責任です。

関数へのポインタ

関数へのポインタは、非メンバ関数または静的メンバ関数のアドレスで初期化できます。 関数からポインタへの 暗黙変換により、アドレス取得演算子は省略可能です:

void f(int);
void (*p1)(int) = &f;
void (*p2)(int) = f; // &f と同じ

関数や関数への参照とは異なり、関数へのポインタはオブジェクトであるため、配列への格納、コピー、代入などが可能です。

void (a[10])(int);  // エラー: 関数の配列
void (&a[10])(int); // エラー: 参照の配列
void (*a[10])(int); // OK: 関数へのポインタの配列

注: 関数ポインタを含む宣言は、多くの場合型エイリアスを使用して簡略化できます:

using F = void(int); // 宣言を簡略化するための名前付き型エイリアス
F a[10];  // エラー: 関数の配列
F& a[10]; // エラー: 参照の配列
F* a[10]; // OK: 関数へのポインタの配列

関数へのポインタは 関数呼び出し演算子 の左側オペランドとして使用でき、これによって指し示される関数を呼び出します:

int f(int n)
{
    std::cout << n << '\n';
    return n * n;
}
int main()
{
    int (*p)(int) = f;
    int x = p(7);
}

関数ポインタをデリファレンスすると、指し示す関数を識別する左辺値が得られます:

int f();
int (*p)() = f;  // ポインタpはfを指している
int (&r)() = *p; // fを識別する左辺値が参照に束縛されている
r();             // 左辺値参照を通じて関数fが呼び出される
(*p)();          // 関数左辺値を通じて関数fが呼び出される
p();             // ポインタを直接介して関数fが呼び出される

関数へのポインタは、オーバーロードの集合から初期化することができます。この集合には、関数、関数テンプレートの特殊化、および関数テンプレートが含まれる場合がありますが、ポインタの型に一致するオーバーロードが1つだけ存在する場合に限ります(詳細は オーバーロードされた関数のアドレス を参照してください):

template<typename T>
T f(T n) { return n; }
double f(double n) { return n; }
int main()
{
    int (*p)(int) = f; // f<int>をインスタンス化して選択
}

等価比較演算子 は関数へのポインタに対して定義されています(同じ関数を指している場合に等しいと比較されます)。

メンバへのポインタ

データメンバへのポインタ

クラス C のメンバーである非静的メンバーオブジェクト m へのポインタは、 & C :: m という式で正確に初期化できます。 & ( C :: m ) や、 C のメンバー関数内での & m といった式は、メンバーへのポインタを形成しません。

このようなポインタは メンバアクセス演算子 operator. * および operator - > * の右辺オペランドとして使用できます:

struct C { int m; };
int main()
{
    int C::* p = &C::m;          // クラスCのデータメンバmへのポインタ
    C c = {7};
    std::cout << c.*p << '\n';   // 7を出力
    C* cp = &c;
    cp->m = 10;
    std::cout << cp->*p << '\n'; // 10を出力
}

アクセス可能で明確な非仮想基底クラスのデータメンバへのポインタは、 暗黙的に変換 されて、派生クラスの同じデータメンバへのポインタに変換できます:

struct Base { int m; };
struct Derived : Base {};
int main()
{
    int Base::* bp = &Base::m;
    int Derived::* dp = bp;
    Derived d;
    d.m = 1;
    std::cout << d.*dp << ' ' << d.*bp << '\n'; // 1 1 を出力
}

逆方向の変換、派生クラスのデータメンバへのポインタから明確な非仮想基底クラスのデータメンバへのポインタへの変換は、 static_cast および 明示的キャスト によって許可されます(基底クラスがそのメンバを持っていない場合でも、最も派生したクラスが持っており、ポインタがアクセスに使用されるときに):

struct Base {};
struct Derived : Base { int m; };
int main()
{
    int Derived::* dp = &Derived::m;
    int Base::* bp = static_cast<int Base::*>(dp);
    Derived d;
    d.m = 7;
    std::cout << d.*bp << '\n'; // 正常: 7を出力
    Base b;
    std::cout << b.*bp << '\n'; // 未定義動作
}

メンバへのポインタが指す型は、それ自体がメンバへのポインタである可能性があります:メンバへのポインタは多段階にでき、各レベルで異なるcv修飾を持つことができます。ポインタとメンバへのポインタの混合多段階組み合わせも許可されます:

struct A
{
    int m;
    // 非constメンバへのconstポインタ
    int A::* const p;
};
int main()
{
    // 非constメンバへのconstポインタであるデータメンバへの非constポインタ
    int A::* const A::* p1 = &A::p;
    const A a = {1, &A::m};
    std::cout << a.*(a.*p1) << '\n'; // 1を出力
    // constポインタ-to-memberへの通常の非constポインタ
    int A::* const* p2 = &a.p;
    std::cout << a.**p2 << '\n'; // 1を出力
}

メンバ関数へのポインタ

クラス C のメンバーである非静的メンバー関数 f へのポインタは、式 & C :: f で正確に初期化できます。 & ( C :: f ) や、 C のメンバー関数内での & f のような式は、メンバー関数へのポインタを形成しません。

このようなポインタは メンバアクセス演算子 operator. * および operator - > * の右辺オペランドとして使用できます。 結果の式 は関数呼び出し演算子の左辺オペランドとしてのみ使用できます:

struct C
{
    void f(int n) { std::cout << n << '\n'; }
};
int main()
{
    void (C::* p)(int) = &C::f; // クラスCのメンバ関数fへのポインタ
    C c;
    (c.*p)(1);                  // 1を出力
    C* cp = &c;
    (cp->*p)(2);                // 2を出力
}


基底クラスのメンバ関数へのポインタは、 暗黙的に変換 されて、派生クラスの同じメンバ関数へのポインタになることができます:

struct Base
{
    void f(int n) { std::cout << n << '\n'; }
};
struct Derived : Base {};
int main()
{
    void (Base::* bp)(int) = &Base::f;
    void (Derived::* dp)(int) = bp;
    Derived d;
    (d.*dp)(1);
    (d.*bp)(2);
}
**注記**: 提供されたコードはC++のメンバ関数ポインタの例であり、HTMLタグ内のコードブロックは翻訳対象外のため、上記のコード部分は変更せずにそのまま保持されています。コードの内容はBaseクラスとDerivedクラスのメンバ関数ポインタの互換性を示すものです。

逆方向の変換、派生クラスのメンバ関数ポインタから明確な非仮想基底クラスのメンバ関数ポインタへの変換は、 static_cast および explicit cast によって許可されます(基底クラスがそのメンバ関数を持っていない場合でも、最も派生したクラスが持っており、ポインタがアクセスに使用されるときに限ります):

struct Base {};
struct Derived : Base
{
    void f(int n) { std::cout << n << '\n'; }
};
int main()
{
    void (Derived::* dp)(int) = &Derived::f;
    void (Base::* bp)(int) = static_cast<void (Base::*)(int)>(dp);
    Derived d;
    (d.*bp)(1); // 正常: 1を出力
    Base b;
    (b.*bp)(2); // 未定義動作
}

メンバ関数へのポインタは、コールバックまたは関数オブジェクトとして使用されることがあり、多くの場合 std::mem_fn または std::bind を適用した後に使用されます:

#include <algorithm>
#include <cstddef>
#include <functional>
#include <iostream>
#include <string>
int main()
{
    std::vector<std::string> v = {"a", "ab", "abc"};
    std::vector<std::size_t> l;
    transform(v.begin(), v.end(), std::back_inserter(l),
              std::mem_fn(&std::string::size));
    for (std::size_t n : l)
        std::cout << n << ' ';
    std::cout << '\n';
}

出力:

1 2 3

ヌルポインタ

すべての型のポインタは、その型の nullポインタ値 として知られる特別な値を持ちます。値がnullであるポインタは、オブジェクトや関数を指しません(nullポインタをデリファレンスする動作は未定義です)、そして値が同様に null である同じ型のすべてのポインタと等しいと比較されます。

null pointer constant は、ポインタをnullに初期化するため、または既存のポインタにnull値を代入するために使用できます。これは以下のいずれかの値です:

  • 値がゼロの整数リテラル。
(C++11以降)

マクロ NULL も使用可能であり、これは実装定義のヌルポインタ定数に展開されます。

Zero-initialization および value-initialization もポインタをそのnull値に初期化します。

ヌルポインタはオブジェクトが存在しないことを示すために使用できます(例: std::function::target() )、または他のエラー状態の指標としても使用されます(例: dynamic_cast )。一般的に、ポインタ引数を受け取る関数は、値がヌルかどうかをチェックし、そのケースを別途処理する必要がほとんどです(例えば、 delete expression はヌルポインタが渡された場合には何も行いません)。

無効なポインタ

ポインタ値 p は、以下の条件のいずれかを満たす場合、評価 e コンテキストにおいて有効 である:

  • p はヌルポインタ値です。
  • p は関数へのポインタです。
  • p はオブジェクト o の終端またはそれを超える位置を指すポインタであり、 e o のストレージ領域の存続期間内にあります。

ポインタ値 p が評価 e で使用され、かつ p e のコンテキストで有効でない場合:

  • e 間接参照 または 解放関数 の呼び出しである場合、動作は未定義です。
  • それ以外の場合、動作は実装定義です。
int* f()
{
    int obj;
    int* local_ptr = new (&obj) int;
    *local_ptr = 1; // OK: 評価「*local_ptr」は
                    // 「obj」のストレージ期間内にある
    return local_ptr;
}
int* ptr = f();  // 「obj」のストレージ期間が終了したため、
                 // 以降のコンテキストにおいて「ptr」は無効なポインタとなる
int* copy = ptr; // 実装定義の動作
*ptr = 2;        // 未定義動作: 無効なポインタの間接参照
delete ptr;      // 未定義動作: 無効なポインタからのストレージ解放

Const性

  • cv がポインタ宣言内で * の前に現れる場合、それは宣言指定子シーケンスの一部であり、指し示されるオブジェクトに適用されます。
  • cv がポインタ宣言内で * の後に現れる場合、それは 宣言子 の一部であり、宣言されているポインタ自体に適用されます。
構文 意味
const T * 定数オブジェクトへのポインタ
T const * 定数オブジェクトへのポインタ
T * const オブジェクトへの定数ポインタ
const T * const 定数オブジェクトへの定数ポインタ
T const * const 定数オブジェクトへの定数ポインタ
// pc は const int への非constポインタ
// cpc は const int へのconstポインタ
// ppc は const int への非constポインタへの非constポインタ
const int ci = 10, *pc = &ci, *const cpc = pc, **ppc;
// p は非const int への非constポインタ
// cp は非const int へのconstポインタ
int i, *p, *const cp = &i;
i = ci;    // 正常: const int の値が非const int にコピーされる
*cp = ci;  // 正常: constポインタが指す非const int は変更可能
pc++;      // 正常: const int への非constポインタは変更可能
pc = cpc;  // 正常: const int への非constポインタは変更可能
pc = p;    // 正常: const int への非constポインタは変更可能
ppc = &pc; // 正常: const int へのポインタのアドレスは const int へのポインタへのポインタ
ci = 1;    // エラー: const int は変更不可
ci++;      // エラー: const int は変更不可
*pc = 2;   // エラー: 指し示されたconst int は変更不可
cp = &ci;  // エラー: 非const int へのconstポインタは変更不可
cpc++;     // エラー: const int へのconstポインタは変更不可
p = pc;    // エラー: 非const int へのポインタはconst int を指せない
ppc = &p;  // エラー: const int へのポインタへのポインタは
           // 非const int へのポインタを指せない

一般的に、ある多段階ポインタから別の多段階ポインタへの暗黙的変換は、 資格変換 で説明されている規則に従います。

複合ポインタ型

比較演算子のオペランド、または 比較演算子 の第2オペランドと第3オペランドのいずれかがポインタまたはポインタ-to-memberである場合、これらのオペランドの共通型として複合ポインタ型が決定されます。

2つのオペランド p1 p2 がそれぞれ T1 T2 の型を持つ場合、 p1 p2 が複合ポインタ型を持つのは、以下の条件のいずれかが満たされる場合に限ります:

  • p1 p2 は両方ともポインタである。
  • p1 p2 の一方がポインタで、もう一方のオペランドがヌルポインタ定数である。
  • p1 p2 は両方ともヌルポインタ定数であり、かつ T1 T2 の少なくとも一方が非整数型である。
(C++11以降)
(C++14まで)
  • T1 T2 の少なくとも一方がポインタ型、メンバポインタ型、または std::nullptr_t である。
(C++14以降)

合成ポインタ型 C は、 p1 p2 の以下のように決定されます:

  • p1 ヌルポインタ定数 の場合、 C T2 となる。
  • それ以外の場合、 p2 がヌルポインタ定数の場合、 C T1 となる。
(C++11以前)
  • p1 p2 がともに ヌルポインタ定数 の場合、 C std::nullptr_t となる。
  • それ以外の場合、 p1 がヌルポインタ定数の場合、 C T2 となる。
  • それ以外の場合、 p2 がヌルポインタ定数の場合、 C T1 となる。
(C++11以降)
  • それ以外の場合、以下のすべての条件が満たされるならば:
  • T1 または T2 のいずれかが「 cv1 void へのポインタ」である。
  • もう一方の型が「 cv2 T へのポインタ」であり、ここで T オブジェクト型 または void である。
C は「 cv12 void へのポインタ」であり、ここで cv12 cv1 cv2 の和集合である。
  • それ以外の場合、以下の条件がすべて満たされる場合:
  • T1 または T2 が「関数型 F1 へのポインタ」である。
  • もう一方の型が「noexcept関数型 F2 へのポインタ」である。
  • F1 F2 はnoexceptを除いて同一である。
C は「 F1 へのポインタ」となる。
(C++17以降)
  • それ以外の場合、以下のすべての条件が満たされるならば:
  • T1 は「 C1 へのポインタ」です。
  • T2 は「 C2 へのポインタ」です。
  • C1 C2 のいずれか一方が他方に対して reference-related です。
C
  • C1 C2 に対してreference-relatedである場合、 T1 T2 qualification-combined type 、または
  • C2 C1 に対してreference-relatedである場合、 T2 T1 のqualification-combined typeです。
  • それ以外の場合、以下の条件がすべて満たされる場合:
  • T1 または T2 が「関数型 F1 C1 のメンバへのポインタ」である。
  • もう一方の型が「noexcept関数型 F2 C2 のメンバへのポインタ」である。
  • C1 C2 のいずれかがもう一方に対して参照関連(reference-related)である。
  • F1 F2 がnoexceptを除いて同一である。
C
  • C1 C2 に対して参照関連である場合、「型 F1 C2 のメンバへのポインタ」、または
  • C2 C1 に対して参照関連である場合、「型 F1 C1 のメンバへのポインタ」である。
(C++17以降)
  • それ以外の場合、以下のすべての条件が満たされるならば:
  • T1 は「非関数型 M1 C1 メンバへのポインタ」です。
  • T2 は「非関数型 M2 C2 メンバへのポインタ」です。
  • M1 M2 はトップレベルのcv修飾を除いて同じ型です。
  • C1 C2 の一方が他方に対してreference-relatedです。
C は以下のいずれかです:
  • C1 C2 に対してreference-relatedの場合、 T2 T1 の修飾結合型(qualification-combined type)、または
  • C2 C1 に対してreference-relatedの場合、 T1 T2 の修飾結合型(qualification-combined type)。
  • それ以外の場合、 T1 T2 類似型 である場合、 C T1 T2 の修飾子合成型となる。
  • それ以外の場合、 p1 p2 は複合ポインタ型を持たず、 C を決定する必要があるプログラムはそのような型に対して不適格となる。
using p = void*;
using q = const int*;
// 「p」と「q」の複合ポインタ型の決定は
// [「cv1 voidへのポインタ」と「cv2 Tへのポインタ」]の場合に該当:
// cv1 = 空, cv2 = const, cv12 = const
// 「cv12 = const」を「cv12 voidへのポインタ」に代入:
// 複合ポインタ型は「const void*」
using pi = int**;
using pci = const int**;
// 「pi」と「pci」の複合ポインタ型の決定は
// [類似型「C1」と「C2」へのポインタ]の場合に該当:
// C1 = int*, C2 = const int*
// これらは類似型であるため参照関連型(双方向)
// 複合ポインタ型は「p1」と「pc1」
// (または「pci」と「pi」)の修飾結合型:「const int**」

不具合報告

以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。

DR 適用対象 公開時の動作 正しい動作
CWG 73 C++98 オブジェクトへのポインタは配列の終端を過ぎた位置へのポインタと
決して等しくならない
非ヌルかつ非関数ポインタの場合、
それらが表すアドレスを比較する
CWG 903 C++98 0と評価されるあらゆる整数定数式が
ヌルポインタ定数と見なされていた
値0の整数リテラルに
限定される
CWG 1438 C++98 無効なポインタ値のあらゆる使用方法の
動作は未定義だった
間接参照と解放関数への
渡し以外の動作は
実装定義となる
CWG 1512
( N3624 )
C++98 複合ポインタ型のルールが不完全で、
int ** const int ** の比較を
許可していなかった
完全なものとした
CWG 2206 C++98 void へのポインタと関数へのポインタが
複合ポインタ型を持っていた
それらはそのような型を持たない
CWG 2381 C++17 複合ポインタ型を決定する際に関数ポインタ変換が
許可されていなかった
許可される
CWG 2822 C++98 記憶域の領域の存続期間の終了に達すると
ポインタ値が無効化される可能性があった
ポインタの有効性は
評価コンテキストに基づく
CWG 2933 C++98 関数へのポインタは常に無効だった それらは常に有効である

関連項目

C documentation for Pointer declaration
日本語訳:
C documentation Pointer declaration
変更点: - "for" → "の"(C documentation for Pointer declaration → Pointer declarationのC documentation) - HTMLタグ、属性、C++専門用語(Pointer declaration)は翻訳せず保持 - 元のフォーマットを完全に維持