3

おそらく、C ++で参照によってリテラルを返すことは、リテラルがスコープ外になり、関数を離れるため、悪いことです。

const char &ToBoolean(bool val) const 
{ 
    return val ? (const char &)"1" : (const char &)"0"; 
}

、しかし、使用するときinlineは、リテラルのスコープが呼び出し元の関数にあるので、これは問題ないはずだと思いますか、それとも違いますか?例:

inline const char &ToBoolean(bool val) const 
{ 
    return val ? (const char &)"1" : (const char &)"0"; 
}

これが私がそれを使うことを計画している方法です:

void testToBoolean1()
{
     bool val = true;
     const char *valStr = ToBoolean(val);
     int result = strcmp("1", valStr);
     CPPUNIT_ASSERT_EQUAL(0, result);
}

アップデート。

静的な文字列で問題がない場合は、これはどうでしょうか。

inline const char *ToBoolean(bool val) const { 
    char boolStr[6];
    if (val) strcpy(boolStr, "true");
    else strcpy(boolStr, "false");
    return &boolStr;
}

これは、VC++2012を使用して正常にコンパイルおよび実行されます。

4

4 に答える 4

5

文字列リテラルはローカル変数とは異なり、プログラムの存続期間中は存続します。有効期間は静的です。文字列リテラルへのポインタを安全に返すことができます。

C ++ 11標準§2.14.5.8:

通常の文字列リテラルおよびUTF-8文字列リテラルは、ナロー文字列リテラルとも呼ばれます。狭い文字列リテラルの型は「arrayofnconst char」です。ここで、nは以下に定義する文字列のサイズであり、静的ストレージ期間(3.7)があります。

3.7.1静的保存期間
パラ1:

...これらのエンティティのストレージは、プログラムの期間中持続するものとします(3.6.2、3.6.3)


明確にするために、文字列リテラル「1」のタイプはですchar (*)[2]。これは、「1」の型がchar [2]であり、2文字の配列へのポインタがとして宣言されてchar (*)[2]いるためです。したがって、アドレスを取得する必要がある場合。参照を返すとき、暗黙のcスタイルのキャストはに発展しますreinterpret_cast。これは基本的に、正確さに関係なく、任意のタイプのポインターを他のタイプにキャストできます。あなたの場合にそれがあなたを得るのは未定義の振る舞いです。上記のように、安全に返すことができるのは、文字列リテラルへのポインタです。返品タイプを次のように変更する必要があります。

char const* ToBoolean(bool val) const;

更新されたQへの回答:

更新されたソリューションは、文字列リテラルを関数のローカル配列にコピーするだけです。配列は関数の範囲を超えて存在しません。だから、それは大丈夫ではありません。動作しているように見えるかもしれませんが、未定義動作を呼び出します。「true」と「false」自体には静的な期間の有効期間がありますが、それらへのポインタを返していません。それらをローカル配列にコピーし、ローカル配列へのポインタを返しています。

于 2013-03-24T11:52:26.803 に答える
4

char const*はcharconst&と同じではありません(前者はcharへのポインタであり、後者は単一のcharへの参照です。文字列定数は静的に割り当てられるため、関数からそれらへのポインタを安全に返すことができます。

inline char const* ToBoolean(bool val) const 
{ 
    return val ? "1" : "0"; 
}
于 2013-03-24T11:53:06.527 に答える
2

"1"タイプ「配列2」の文字列リテラルですconst char。でキャストすると(const char &)"1"、結果としてreinterpret_cast<const char&>("1")未定義の動作が発生します。

おそらくあなたはするつもりです:

inline const char &ToBoolean(bool val)
{ 
    return val ? '1' : '0'; 
}

一重引用符に注意してください。これらは、文字列リテラルではなく、文字リテラルです。

ただし、文字リテラルはprvaluesであるため、const char&結果にバインドすると、対応する値で一時オブジェクトが作成されます。次に、参照はその一時オブジェクトにバインドされます。ただし、その一時オブジェクトは完全な式(returnステートメント)の最後で破棄され、参照はぶら下がったままになります。

いいえ、inline変数のスコープやオブジェクトの存続期間には影響しません。それはコンパイラーに何をすべきかについてのヒントにすぎないので、それはばかげているでしょう。つまり、コンパイラは、必要に応じてコードの意味を変更することを選択できます。

したがって、代わりに、文字列リテラルへのポインタを返してみてください。

inline const char* ToBoolean(bool val)
{ 
    return val ? "1" : "0"; 
}

文字列リテラルには静的な保存期間があります。つまり、プログラムの期間中存在します。文字列リテラルの最初の要素へのポインタを返し、それが指すオブジェクトが常に有効であることを確認できます。

于 2013-03-24T11:58:59.543 に答える
1
inline const char &ToBoolean(bool val) const 
{ 
    return val ? (const char &)"1" : (const char &)"0"; 
}

char?の文字列を返します -また、本当に返す必要がある場合はconst char *、明示的に記述してください。::

inline const char *ToBoolean(bool val) const 
{ 
    return val ? "1" : "0"; 
}
于 2013-03-24T11:53:59.610 に答える