2009-05-29 14 views
16

私はC++の初心者ですので、質問があまりにも基本的であれば申し訳ありません。C++空文字列コンストラクタ

私は文字列constrctursを収集し、それらを覚えてみることを試みました。

string strA();   // string(); empty string // incorrect 
string strB("Hello"); // string(const char* str) 
string strC("Hello",3); // string(const char* str, size_type length) 
string strD(2,'c');  // string(size_type lenght, const char &c) 
string strE(strB);  // string(const string& s) 

cout << strA << endl; 
cout << strB << endl; 
cout << strC << endl; 
cout << strD << endl; 
cout << strE << endl; 

それらのすべては、ストラを除いて動作します。 "1"が印刷されます。 なぜですか?この場合のstrAのタイプは何ですか?私が不確かなときに、どのように物の種類を確認できますか?

私は正しい方法は、(時には何の括弧を括弧ない、途中で他のコンストラクタと矛盾するように思われた)このあることに気づいた:

string strA; 

PS:太字の質問、通常は無関係答えは下落します。

答えて

32

これは非常に人気のある落ち物です。 C++文法はあいまいです。あいまいさを解決するためのルールの1つは、「宣言のようなものが宣言であるかどうか」です。この場合、変数を定義する代わりに関数プロトタイプを宣言しました。

string strA(); 

string strA(void); 

文字列を返す引数なしの関数のプロトタイプと等価です。

明示的にこれを試して、引数なしのコンストラクタを呼び出していないことを望む場合:

string strA=string(); 

それは完全に同じではありません - それは引数なしのコンストラクタを使用して、一時的な文字列を作成意味し、その変数を初期化するために、それをコピーしますstrA 'になりますが、コンパイラーはそれを最適化してコピーを省略することができます。

EDIT: Here is an appropriate item in C++ FAQ Lite

+3

これが私がC++の使用をやめた理由の1つです。 –

+3

@Dietrich Epp:これも私を悩ませました。私はCの互換性を保つために支払った価格だと思います。そのメトリックトンの問題を抱えているCを使用している代わりに、私の推測ではC++を保ち、その落とし穴を避ける方が良いということです。 – paercebal

+0

'std :: string strA(" ");' – CaptainDaVinci

13

これは、関数宣言として

string strA(); 

を考慮する。デフォルトコンストラクタの使用のために

C++で
string strA; 
+2

ヒープを割り当て解除するときにその表記法を使用できます。 string * strA = new string(); – Skilldrick

6

、Cのように、declarartionのように見える何かが宣言として扱われることを言うルールがあります。

string strA(); 

は、関数宣言のように見えるので、1として扱われます。次のものが必要です。

string strA; 
1

コンパイラは、無効な引数を取り、文字列型のオブジェクトを返す関数の関数プロトタイプとしてstring strA()解釈します。空の文字列オブジェクトを作成する場合は、string strA;(paranthesisなし)を使用してください。

3

関数へのポインタは、常にtrueとして数値に変換されているので、それは1を印刷します。

+5

関数のポインタがnullでない場合のみです。とにかく、関数へのポインタはその定義を指していなければなりません。これはリンクしてはいけません。 – MSalters

2

なぜtkopecはうまくいかないのですか?あなたの2番目の質問に答えるために、ここにあなたがタイプをチェック方法は次のとおりです。

template<typename TEST> void Error_() { 
    TEST* MakeError = 1; 
} 

Error_(StrA);を呼び出すことにより、コンパイルエラーが発生します、そして、あなたのコンパイラは、おそらくそれが今Error_< std::basic_string<char, std::allocator<char> > (*)(void)>(std::basic_string<char, std::allocator<char> > (*)(void)) で起こったことを教えてくれます、のstd ::のbasic_string> std :: stringなので、これは実際にはError_< std::string (*)(void)> (std::string (*)(void))を意味します。 '<>'の部分は '()'の間で繰り返され、それはstrAの型です。この場合、std::string (*)(void)

+0

strAのタイプは関数です。 std :: string(void)。これは関数ポインタではありません。彼はそれを文字列(* strA)()として宣言しなければなりません。もし彼がそれを関数ポインタにしたいならば。私はおそらくあなたが何を意味したのか知っているでしょうが、あなたの最後の文章は、それが関数ポインタだと言うように聞こえます。 –

4

この場合、「宣言であれば宣言である」というルールは当てはまりません。以下では、両方ものが宣言

string a; 
string a(); 

あるので一つはオブジェクトの宣言であり、他方は、関数の宣言です。このルールは他の場合に適用されます。たとえば、この場合:

string a(string()); 

この場合、string()は2つのことを意味します。デフォルトを作成

  • 無名の関数パラメータの宣言
  • 発現はfuleはここに適用され、string()は名前が無関係である(以下、という名前のパラメータと同じ意味に取られるstring

を構築しました関数を宣言する際のパラメータ内のパラメータ)

string a(string im_not_relevant()); 

関数がパラメータとして配列またはanotをとる場合そのパラメータはポインタに崩壊します。関数パラメータの場合、関数へのポインタ。このように、それはより身近

string a(string (*im_not_relevant)()); 

を見てしかし、あなたの場合には、それはむしろ道になってきた構文だことがあり、以下、同等です。以下は関数宣言です。これは、オブジェクトの宣言になることはありません(それはおそらく、プログラマが意図したにもかかわらず!)

string a(); 

だから、最初の場所でこのような状況にはあいまいさがないので、それは関数を宣言します。 stringにはユーザ定義のコンストラクタがあるので、カッコを省略することができ、その結果は意図したとおりに変わりません。

関連する問題