8

C 標準では _ _ func _ _ value が常に囲んでいる関数の名前であることが保証されているのに、C++ (もちろん C++11 のことです) では実装定義の任意の文字列 (たとえば、パラメータなしの関数 foo がある場合、「Some string fdgdg asdfs fsdf sd」のようなものを取得できます)?

ISO/IEC 9899:2011

6.4.2.2 事前定義された識別子

セマンティクス

1 識別子 _ _ func _ _ は、各関数定義の左中括弧の直後に宣言 static const char _ func _ [] = "function-name";のように、翻訳者によって暗黙的に宣言されるものとします。function-name は字句的に囲んでいる関数の名前です。

ISO/IEC 14882:2011

8.4.1 一般 [dcl.fct.def.general]

8 関数ローカルの定義済み変数 _ _ func _ _ は、静的 const char _ _ func _ _ [] = "関数名 "; という形式の定義であるかのように定義されます。function-name は実装定義の文字列です。そのような変数が、プログラム内の他のオブジェクトのアドレスとは異なるアドレスを持つかどうかは指定されていません。

そして、これの理由は何ですか?現在の関数名を取得できない場合、「不明」のようなものを返しますか?

4

3 に答える 3

14

C++の関数の「名前」は何ですか?

  • 名前空間によって修飾されていますか?
  • オーバーロードされた関数は、パラメーターの型によって名前が付けられていますか?
  • オーバーロードに使用されない戻り値の型はどうですか?
  • 関数テンプレートではどうなりますか?
  • 呼び出し規約は名前の一部ですか?
  • 「const」と「volatile」は型名の前後どちらに書くべきですか?

「実装定義の文字列」により、コンパイラは、このすべての情報を文字列に詰め込む方法にある程度の柔軟性を与えます。そして、移植性が必要な場合は、文字列の比較や解析を実行したり、実際には値をログに記録する以外は何もしないでくださいというメッセージがプログラマーに送信されます。

(これらの値が一意であるという保証はないため、これらの値を互いに比較することさえできません。すべてのオーバーロードが同じ文字列を生成する可能性があるようです。したがって、プロファイラー統計のコンパイルに使用することはお勧めできません。)

于 2013-01-04T20:14:12.250 に答える
4

これは、C++ コンパイラが でマングルされた名前を使用できるようにするためだと思われ__func__ます。

于 2013-01-04T20:14:28.577 に答える
3

C++ ではパラメーターの型に基づく関数のオーバーロードが許可されており、関数は非グローバル スコープに配置できるため (どちらも標準 C では許可されていません)、字句的に囲んでいる関数の単純な名前では十分ではありません。それを識別するために。

たとえば、次のことを考慮してください。

class A {
public:
    A() {
        std::cout << __func__ << std::endl;
    }
    void funca() {
        std::cout << __func__ << std::endl;
    }
};

int main() {
    A a;
    a.funca();
}

何を印刷する必要がありますか?

GCC は "A" と "funca" を出力するプログラムを生成しますが、標準では "A::A" と "a::funca" を出力することを許可していますが、これは C 標準では許可されていません。

于 2013-01-04T20:18:35.963 に答える