C ++でCヘッダーを使用する場合、std ::またはグローバル名前空間の関数を使用する必要がありますか?


113

Cは、正確ではありませんが、C ++のサブセットです。そのため、名前を少し(stdio.hto cstdiostdlib.hto cstdlib)変更することで、C ++でほとんどのC関数/ヘッダーを使用できます。

私の質問は、実際には一種の意味論です。C ++コード(GCCコンパイラの最新バージョンを使用)では、呼び出すことができますがprintf("Hello world!");std::printf("Hello world!");まったく同じように機能します。そして、私が使用しているリファレンスでは、としても表示されstd::printf("Hello world!");ます。

私の質問は、std::printf();C ++で使用する方が良いですか?違いはありますか?


17
ある日C、グローバルネームスペースへのライブラリシンボルのダンプが違法であることが義務付けられた場合、私はstd::適格バージョンを使用することを好みます。(さらに、私は彼らがそれを違法にしたことを望みます)
Galik

3
@Galik:そうですね。それは、C ++コンパイラを使用したCの問題に関する多くの愚かな質問を安全にします。
このサイトには正直すぎます。

7
「少し妊娠」はありません。Cはサブセットかそうでないかのどちらかです。事実は、そうではありません。これが、C ++で機能するようにCヘッダーを変更する必要がある理由です。
このサイトには正直すぎます

2
「ほとんどすべて」は、数え切れないほど多くの要素のセットについて話すとき、かなり役に立たない測定です。同じ議論によって、おそらくCとJavaを関連付けることができます。
Daniel Jour

9
@ささうけいいえ、それはサブセットではありません。CとC ++は確実にサブセットを共有しますが、C自体 C ++のサブセットではありません
常磁性クロワッサン2015

回答:


106

C ++ 11標準(強調鉱山)から:

D.5 C標準ライブラリヘッダー[depr.c.headers]

  1. C標準ライブラリとの互換性のために...
  2. それぞれがname.hという形式の名前を持つすべてのCヘッダーは、対応するcnameヘッダーによって標準ライブラリの名前空間に配置された各名前がグローバル名前空間スコープ内に配置されているかのように動作しますこれらの名前が最初に名前空間スコープ内で宣言または定義されるかどうか指定されていません(3.3.6)名前空間STD、次いで明示的な使用、宣言(7.3.3)によってグローバルネームスペーススコープに注入されます。
  3. 例:ヘッダーは、名前空間内での宣言と定義を<cstdlib> 確実に提供します std。また、グローバル名前空間内でこれらの名前を提供する場合もあります。ヘッダーは、C標準と同様に、グローバル名前空間内で同じ宣言と定義を<stdlib.h> 確実に提供します。名前空間内でこれらの名前を提供することもあります。std

«name.h»ヘッダーの使用は非推奨で、将来のリビジョンから削除する候補として識別されています。

そのため、«cname»ヘッダーを含め、std名前空間の宣言と定義を使用することをお勧めします。

何らかの理由で«name.h»ヘッダーを使用する必要がある場合(非推奨、上記を参照)、グローバル名前空間の宣言と定義を使用することをお勧めします。

言い換えれば、好む

#include <cstdio>

int main() {
    std::printf("Hello world\n");
}

以上

#include <stdio.h>

int main() {
    printf("Hello world\n");
}

1
N3242はC ++標準ではありません。N3337 C ++ 11との違いが最も少ないドラフト。
MM

3
また、Jonathan WakelyのWhy <cstdlib>が Red Hatブログから想像するよりも複雑である理由もご覧ください。彼は、C ++標準ライブラリの実装者の観点から多くの問題を詳しく説明しています。彼はまた、C ++ 98にさかのぼる歴史を提供します。
jww 2017年

@sergej-この件に関するC ++ 03の扱いを知っていますか?それとも、何が起こるか見当違いですか?
jww 2017年

5
<name.h>は廃止される可能性があり、すぐに削除される可能性はありません。実際、まったく逆です。非推奨のラベルを削除する提案があります。open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0619r0.html # 3.5を参照してください。「最後に、CおよびPOSIXとの重要な互換性レイヤーとして、Cヘッダーが本質的に永久に保持されることは明らかであるようです。ヘッダーを非推奨にする価値があるかもしれません[..]」
Sjoerd

81

<cmeow>常に提供し::std::purr、提供する場合としない場合があります::purr

<meow.h>常に提供し::purr、提供する場合としない場合があります::std::purr

含めるヘッダーによって提供されることが保証されているフォームを使用してください。


7
変装したSTL?
nwp

@nwpいいえ。(15文字)
TC

@TC残念ながら、コンパイラで試したところ、どちら<cmeow><meow.h>提供せず、プリプロセッサエラーも提供してい::std::purrません::purr<cstdio>および/または<stdio.h>提供::std::printfおよび/またはのみ::printf。:P
LF

4
@LFあなたがstrcat生産する必要があるかもしれません::purr
ランディン

8

いいえ、どちらの方法でも大丈夫です。

オリジナルの意図は、ということでした<___.h>ヘッダがグローバル名前空間にすべてをかけるCバージョンとなり、そして<c___>ifiedバージョンでの場所のすべて-ヘッダはC ++になりstd、名前空間。

実際には、しかし、C ++のバージョンでは、また、グローバル名前空間にすべてをかけます。そして、を使用するという明確なコンセンサスはありませんstd::バージョンことが「正しいこと」であるはありません。

したがって、基本的には、好きな方を使用してください。最も一般的なのは、おそらくC printfではなくグローバルネームスペースでC標準ライブラリ関数を使用することですが、std::printf一方を「優れている」と考える理由はそれほど多くはありません。


2
「そして、std ::バージョンを使用することが「正しいこと」であるという明確な合意はありません。」ええ、はい、それが正しいことであるというコンセンサスがあります。
Miles Rout 2015

4
コンセンサスに達したかどうかをどのように客観的に判断しますか?
Jeremy Friesner、2015

9
@JeremyFriesnerあなたはそれについてSOに投稿し、反対するコメントを得るかどうかを確認します。:)
jalf

1
@JeremyFriesner:標準では、C ++ヘッダーバージョンが識別子をグローバルネームスペースに配置することを保証していません。この規格では、Cヘッダーバージョンも非推奨になっています。それは私にはかなりコンセンサスに見えます。;-)
DevSolar 2015

2
@DevSolarは、「コンセンサス」という単語を辞書で調べます。それは標準が言うことではなく、C ++プログラマが言うこと、そして特に彼らが何をするかについてです。あります理由文字通りすべての標準ライブラリの実装はCヘッダを提供することは、および C ++のヘッダが同様にグローバル名前空間ですべてを入れています。:)
2015

3

唯一の違いは、スコープ解決をstd::printf()追加することstd::で、将来、同じ名前の関数を誰かが作成することから保護され、名前空間の競合が発生することです。どちらの使用方法でも、まったく同じOS API呼び出しになります(Linuxでを実行して確認できますstrace your_program)。

誰かがそのような関数に名前を付けることは非常にありそうにありません。それprintf()は、世の中で最も一般的に使用される関数の1つであるためです。また、C ++では、iostreamsはcstdioprintfなどの関数の呼び出しよりも優先されます。


1
それどころか、printfC ++では強力な型指定がないためにひどく壊れているため、それをより良いバージョンに置き換えるのはかなり自然です。
Konrad Rudolph、

1
@KonradRudolph必要に応じてその方法で見つけることができますが、間違っているでしょう。強い型付けをすることを意図したものではなく、必要な強い型付けでは簡単に解決できない多くの問題があります。これが、多くの同等のC ++ソリューションがprintfよりもはるかに遅い理由です。「より良い」バージョンに置き換えたい場合は、言語とプログラマーの間の契約を破っていて、そもそも罪の状態にあります。
アリス

1
@Aliceええと、私は契約を破っているわけではありません。std::printfとは異なりmynamespace::printf、C ++では、内部の関数からの名前を隠す名前を持つ独自の関数を明示的に定義できますstd。それは単に議論の余地がないことです。printf緩いタイピングのために効率的であるというあなたの主張については、もちろんそれも間違っています。printfは特に効率的でもありませんが、強く型付けされたより効率的な実装が数多くあります。
Konrad Rudolph

@KonradRudolph間違いです。標準で書かれた、数量詞なしのprintfがC構文に明確に適用されるという契約を破っています。ネームスペースを使用して、グローバルネームスペースにエイリアスを付けることはお勧めできません。それは単に議論の余地がないことです。
アリス

5
@アリスこれの基準を引用していただけますか?私はそのような言い回しを知りません。
Konrad Rudolph

3

C ++ 11標準から:

それぞれがname.hという形式の名前を持つすべてのCヘッダーは、対応するcnameヘッダーによって標準ライブラリの名前空間に配置された各名前がグローバル名前空間スコープ内に配置されているかのように動作します。これらの名前が最初に名前空間stdの名前空間スコープ(3.3.6)内で宣言または定義され、次に明示的なusing宣言(7.3.3)によってグローバル名前空間スコープに注入されるかどうかは指定されていません。

したがって、を使用する場合<cstdio>、それprintfはに含まれるnamespace stdため、グローバル名前空間には含まれません。
グローバル名前空間を使用すると、名前の競合が発生します。これはC ++の方法ではありません。

したがって、私は<cstdio>ヘッダーを使用しており、そうすることをお勧めします。


4
私はそれがこのように機能したいのですが、これは真実ではありません。これを含める<cstdio>と、std :: printfが存在することが保証されますが、:: printfが存在するかどうかも標準からは保証されません。実際には、私が今までの:: printfの聞いたすべてのコンパイラにされ、あなたが含まれている場合にグローバル名前空間に注入<cstdio>
wjl 2015

3

私自身の実践から:std::接頭辞を使用します。そうしないと、浮動小数点を使用している場合に備えて、ある日非常に痛い目abs 遭うでしょう。

非修飾absとはint、一部のプラットフォームで定義された機能を指します。他のものではそれは過負荷です。ただしstd::abs、すべてのタイプで常にオーバーロードされます。


2

printfなしで使用std::すると、いくつかの名前の競合が発生する可能性があり、多くのc ++開発者は悪い習慣と見なしています。グーグルはこれのあなたの友達ですが、ここにいくつかのリンクがあります、これが役に立てば幸いです

「ネームスペースstdの使用」が悪い習慣と見なされるのはなぜですか? http://www.cplusplus.com/forum/beginner/61121/


4
using namespace std悪い習慣ですが、修飾子printfなしでの使用std::はそうではありません。
syntagma

using namespace std;ここでは私の問題ではありません。私はそれを使用することはありません。printf();そして、std::printf();せずにC ++での作業using namespace std;、私は質問を投稿する理由です。
DeiDei

@REACHUS同意しない。2つのシナリオに違いはありません。
Konrad Rudolph、

私は決して使用しません std::printfこと。
trenki

@KonradRudolph私は違いがあるとは言いませんでした、私は自分の意見を表明しました(より多くの論理的根拠については私の答えを参照してください)。
シンタグマ

2

stdioで

これは標準CライブラリヘッダーのC ++バージョンであり、その内容は(ほとんど)そのヘッダーと同じですが、すべて名前空間stcに含まれています(マクロで定義されている名前を除く) C)。

そのため、違いはありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.