44049


自分なりにstaticとinlineの意味をまとめたのですが意味が正しいのかわからないので正しい意味を教えていただきたいです。

  * ヘッダーでinlineを付けた関数は使われる場所に刷り込まれる
  * ヘッダーでstaticを付けた関数は内部結合
  * ヘッダーでstaticを付けたら内部結合？？？
  * クラスでstaticを付けた変数は静的記憶域期間
  * ヘッダーでstaticもinlineも付けずに変数や関数を宣言してはいけない。
  * 関数の中でstaticを付けた変数は静的記憶域期間
  * ソースファイルとヘッダーでstaticを付けた変数は内部結合
  * ソースファイルの一番外でstaticを付けなかった変数は外部結合で同じ名前は使えないが関数は宣言をすると別のソースファイルでも使える。？？？


CC BY-SA 4.0
2018-05-17T11:08:17.803
44042
2018-09-23T06:35:41.727
2018-05-18T00:19:45.770
4236
question
c++
staticとinlineの意味


言語規格でどう言っているかは別にして、`static` には3種類あると思ってください。  
`inline`はまた別の話なので、回答しません。

## トップレベルの変数・関数に対する `static`

変数または関数を内部結合にします。関数の場合、`static`は **宣言** に付ければよく、宣言とは別に **定義**
がある場合、定義の方には付けても付けなくてもよいです。変数の場合は`static`を付けると宣言と定義が分離できません。

内部結合にするという役割のため、
**ヘッダ内でこの`static`を使うことはありません**。ヘッダファイルは他のソースファイルと共有するために作るので、内部結合のものがヘッダにあっても混乱するだけです。

## 関数内のローカル変数に対する `static`

変数を静的記憶域期間にします。

## クラスメンバーに対する `static`

変数を静的記憶域期間にします。つまり、そのクラスのインスタンスの生存期間とは関係のない変数となります。内部結合は関係ありません。  
関数の場合は、そのクラスのインスタンスを必要としないがクラスには属する関数となります。内部結合は関係ありません。

* * *

> //ヘッダーでstaticを付けた関数は内部結合  
>  //ヘッダーでstaticを付けたら内部結合？？？

そうですが、ヘッダで関数や変数にstaticを付けないでください。そういうものはヘッダから削除して、実装ファイル(*.c, *.cc
など)内だけで使います。

> //クラスでstaticを付けた変数は静的記憶域期間

はい。

> //ヘッダーでstaticもinlineも付けずに変数や関数を宣言してはいけない。

変数に関しては、そうです。ヘッダ内では`extern`を付けるはずです。何も付けないと、同じ名前の変数が増殖します。  
関数では問題ありません。何も書かないと`extern`扱いになります。

> //関数の中でstaticを付けた変数は静的記憶域期間

はい。

> //ソースファイルとヘッダーでstaticを付けた変数は内部結合

はい。しかし、ヘッダで`static`変数を宣言しないでください。

> //ソースファイルの一番外でstaticを付けななかった変数は外部結合で同じ名前は使えないが  
>  関数は宣言をすると別にソースファイルでも使える。？？？

外部結合な変数関数は、どこかでで宣言すれば使えるようになります。宣言はヘッダに書いておくのが普通です。


CC BY-SA 4.0
2018-05-17T13:14:03.413
44046
2018-05-17T13:14:03.413
3475
44042
answer


## `static`と`inline`を付けられる場所

  * `static`
    * 関数
    * 変数
    * メンバー関数
    * メンバー変数
  * `inline`
    * 関数
    * メンバー関数
    * 名前空間
  * `static inline`
    * 関数
    * メンバー関数
    * メンバー変数

## `static` の意味

C言語から引き継いでいて全く異なる２つの意味を持ちます。このことが混乱を招いているかもしれません。

### スコープを翻訳単位に制限します。

関数および変数に付けられた際、当該識別子のスコープが`.c`や`.cpp`に制限されます。その結果、異なる`.cpp`にそれぞれ宣言された場合に共存します。例えば

[code]

    // a.h
    static int a;
    
    // b.cpp
    #include "a.h"
    
    // c.cpp
    #include "a.h"
    
[/code]

とした場合、`b.cpp`、`c.cpp`にそれぞれ`static int
a`が存在します。`b.cpp`から`a`を操作しても`c.cpp`の`a`には影響しません。

### 変数に付けられた場合に生存期間をプログラムの終了まで延長します。

関数内の変数、クラス内のメンバー変数は通常、それぞれ関数やクラスの生存期間と一致し、異なる関数呼び出しでは異なる変数を持ちます。しかし、`static`が付けられた場合、関数やクラスに依存せず、プログラムの終了まで値を保持し続けることになります。

なお、関数内の`static`変数は関数の当該行が最初に実行された時点で初期化されます。クラス内の`static`メンバー変数の場合は変数が定義された個所で初期化されます。[C++11からはこの初期化はスレッドセーフに行われる](https://cpprefjp.github.io/lang/cpp11/static_initialization_thread_safely.html)ことが保証されるようになっています。  
２回目以降は初期化が行われず、以前の値をそのまま参照できます。

## `inline`の意味

関数に付けられた場合、その関数がインライン展開されることをコンパイラーに指示します。本当にインライン展開するかどうかはコンパイラーが判断します。クラス定義内にメンバー関数も定義された場合、暗黙的に`inline`指定されたことになります。

そのほかにも[C++11からインライン名前空間](https://cpprefjp.github.io/lang/cpp11/inline_namespaces.html)という機能が登場しています。詳しくはリンク先を。

また[C++17からインライン変数](https://cpprefjp.github.io/lang/cpp17/inline_variables.html)という機能も登場しています。  
そもそも[C++11から`static`付けられていないメンバー変数はクラス定義内で初期化できる](https://cpprefjp.github.io/lang/cpp11/non_static_data_member_initializers.html)ようになっています。しかし`static`の付けられたメンバー変数は前述の通り定義された個所で初期化されるため、クラス外での定義が必要でした。それでは不便なのでC++17から`static
inline`が付けられた場合にはクラス定義内で初期化できるようになりました。

* * *

greenteaさん

> 最近の VC++あたりだと、ヘッダファイルだけで全てが完了する勢い。

int32_tさん

> ヘッダで`static`変数を宣言しないでください。

C++言語としてはヘッダファイルを特別視していません。複数回インクルードされることを前提に記述すればそれまでです。VC++に限らずSTL;
標準テンプレートライブラリなども「ヘッダファイルだけで全てが完了する勢い」です。  
特に既に挙げた[ブロックスコープを持つstatic変数初期化のスレッドセーフ化](https://cpprefjp.github.io/lang/cpp11/static_initialization_thread_safely.html)や[インライン変数](https://cpprefjp.github.io/lang/cpp17/inline_variables.html)のおかげでヘッダファイルで完結できることが広がっています。


CC BY-SA 4.0
2018-05-18T01:44:38.840
44049
2018-05-18T01:44:38.840
4236
44042
answer