web-dev-qa-db-ja.com

"std :: size_t"はC ++では意味がありますか?

継承した一部のコードでは、std名前空間修飾子とともにsize_tを頻繁に使用しています。例えば:

std::size_t n = sizeof( long );

もちろん、コンパイルして問題なく実行できます。しかし、私には悪い習慣のようです(おそらくCから持ち越されたのでしょうか?)。

size_tがC++に組み込まれているため、グローバルネームスペースにあるのは本当ではないですか。 C++でsize_tを使用するためにヘッダーファイルインクルードが必要ですか?

この質問をするもう1つの方法は、次のプログラム(noを含む)がすべてのC++コンパイラでcompileを期待されているでしょうか?

size_t foo()
{
    return sizeof( long );
}
58
jwfearn

これに関してstackoverflowの群衆の間で混乱があるようです

::size_tは、下位互換性ヘッダーstddef.hで定義されています。 ANSI/ISO CISO C++には、当初から含まれています。すべてのC++実装はstddef.h(互換性)とcstddefとともに出荷する必要があり、後者のみがstd::size_tを定義し、必ずしも::size_tを定義する必要はありません。 C++標準の付録Dを参照してください。

129

C++標準のパラグラフ4のセクション17.4.1.2は、次のように述べています。

「しかし、C++標準ライブラリでは、宣言と定義(Cでマクロとして定義されている名前を除く)は、名前空間stdの名前空間スコープ(3.3.5)内にあります。」

これには、size-tを定義するcstddefを含む、パターンcnameのヘッダーにあるアイテムが含まれます。

Std :: size_tは実際に正しいです。

41
Don Wakefield

得られる size_tは、たとえば<stddef.h> の代わりに <cstddef>。明らかな利点は見当たらず、この機能は廃止されています。

13
fizzer
std::size_t n = sizeof( long );

実際、あなたは上記の中で特に悪い習慣と思われるものを尋ねていません。 size_tの使用、std名前空間での修飾、...

C++標準に記載されているように(18.1)、size_tは標準ヘッダーで定義された型です。 C言語からの継承の可能性についての考えや印象を捨てることをお勧めします。 C++は別個の異なる言語であり、そのように考えることをお勧めします。独自の標準ライブラリがあり、C++標準ライブラリのすべての要素は名前空間std内で定義されています。ただし、C++プログラムでC標準ライブラリの要素を使用することは可能です。

汚いハックとして含めることを検討します。 C++標準では、ヘッダーの内容は同じか、C標準ライブラリの対応するヘッダーに基づいていると述べていますが、多くの場合、変更が適用されています。つまり、CヘッダーをC++ヘッダーに直接コピー&ペーストするものではありません。

size_tはC++の組み込み型ではありません。 sizeof()の実際の戻り値の型は実装で定義されているため、C++標準はsize_tを定義して統一するため、これは、sizeof()演算子の戻り値の型として使用される整数型の種類を指定するために定義された型です。

次のプログラム(インクルードなし)は、すべてのC++コンパイラでコンパイルされると予想されますか?

size_t foo()
{
    return sizeof( long );
}

C++標準では次のように述べています(1.4):

ライブラリで定義された名前には、名前空間スコープ(7.3)があります。C++変換ユニット(2.1)は、適切な標準ライブラリヘッダー(16.2)を含めることにより、これらの名前にアクセスできます。

Size_tはstd名前空間内で定義された名前であるため、この場合、この名前を使用するすべてのプログラムに対応するヘッダーを含める必要があります。

次に、3.7.3章では次のように述べています。

ただし、std、std :: bad_alloc、およびstd :: size_tの参照は、適切なヘッダーを含めることによって名前が宣言されていない限り、形式が正しくありません。

そのため、size_tを使用していてヘッダーを含まないプログラムは不正な形式です。

4
mloskot

size_tはC++に組み込まれていません。また、デフォルトでは定義されていません。これはGCCでコンパイルできません:

int main(int argc, char** argv) {
size_t size;
}

そうは言っても、size_tはPOSIXの一部であり、<cstdlib>のような基本的なものだけを使用すると、最終的にそれが定義されることになります。

Std :: size_tはC++のsize_tと同等であると主張できます。 Brianが指摘したように、std ::は、全員に当てはまらないグローバル変数の設定を回避するために名前空間として使用されます。これは、ルート名前空間で定義することもできるstd :: stringに似ています。

4
ypnos

他のライブラリが独自のsize_tを定義する場合があります。たとえば、ブースト。 std :: size_tは、C++標準のものを確実に使用することを指定します。

size_tはc ++標準型であり、名前空間std内で定義されています。

2
Brian R. Bondy

GNUコンパイラヘッダーには、

typedef long int __PTRDIFF_TYPE __; 
 typedef unsigned long int __SIZE_TYPE__;

次にstddef.hは次のようなものを含みます

typedef __PTRDIFF_TYPE__ ptrdiff_t; 
 typedef __SIZE_TYPE__ size_t;

そして最後にcstddefファイルには次のようなものが含まれています

#include <stddef.h> 
 
 namespace std {
 
 using :: ptrdiff_t; 
 using :: size_t; 
 
} 

私はそれを明確にする必要があると思います。 <cstddef>をインクルードする限り、size_tはstd名前空間の外でtypedefされてインクルードされたため、size_tまたはstd :: size_tのいずれかを使用できます。効果的に

typedef long int ptrdiff_t; 
 typedef unsigned long int size_t; 
 
 namespace std {
 
 using :: ptrdiff_t; 
 using :: size_t; 
 
} 
2
Martin

説明は十分に明確だと思います。 std::size_tはC++では意味があり、::size_tはCでは(少なくとも)意味があります。

しかし疑問が残る。つまり、::size_tstd::size_tは互換性があると想定しても安全ですか?

純粋なタイプセーフの観点からは、同一でなければならない場所で定義されていない限り、それらは必ずしも同一ではありません。

私は多くがアラを何かを使用していると思います:

----
// a.hpp 
#include <string>

void Foo( const std::string & name, size_t value );

-----
// a.cpp
#include "a.hpp"

using namespace std;

void Foo( const string & name, size_t value ) 
{
  ...
}

したがって、ヘッダーでは必ず::size_tを使用し、ソースファイルではstd::size_tを使用します。互換性が必要ですよね?そうしないと、コンパイラエラーが発生します。

/ Michael S.

2
Michael S