2

コード例:

// Base.hpp
class Base
{
   public:
   void changeInternals();
   int readInternals();
   void printString(std::string& iString);

   private:
   int m_Internal;
};

// Base.cpp
void Base::changeInternals()
{
   m_InternalValue = 5;
}
int Base::readInternals()
{
   return m_InternalValue;
}
void Base::printString(std::string& iString)
{
   std::cout << iString << std::endl;
}

私の理解では、g++ による最適化では、最初の 2 つのメンバー関数 (changeInternal と readInternal) が関数の引数の一部として「this」ポインターを持ち、メンバー変数 m_Internal にアクセスできるようになります。ただし、3 番目のメンバー関数 printString はメンバー変数を表示する必要がないため、引数に this ポインターが含まれていないのでしょうか?

その場合、次のように変更すると:

 void Base::printString(std::string& iString)
 {
    std::cout << boost::lexical_cast<std::string>(m_Internal) << std::endl;
 }

メンバー関数は m_Internal へのアクセスを必要とするため、この関数の呼び出し元は、'this' ポインターの値をレジスターに入れる必要があります。

これによりバイナリ互換性が損なわれることが予想されますが、「バイナリ互換性の落とし穴」のリストでこれを見つけることができないようです。内部に触れるかどうかに関係なく、すべてのメンバー関数に this ポインターがあるという要件はありますか? コアで gdb の出力を調べる (悲しいことに、ここでコピー/貼り付けすることはできません:(、申し訳ありません)。

この質問の目的のために、ここではインライン展開が行われていないと仮定してください (GCC never_inline 属性を介して)

4

1 に答える 1

2

メンバー関数は、使用されているかどうかにかかわらず、ポインターを使用して常に[1]呼び出されます。thisこれは、関数がthisポインターを使用するかどうかをコンパイラーが「知る」必要がないようにするためです。関数がヘッダー ファイルに宣言としてのみ含まれており、実際の実装が別のソース ファイルで個別にコンパイルされている場合を考えてみましょう。thisまたは、関数が仮想であり、複数の可能なクラスがあり、そのうちのいくつかは使用し、一部はメンバー関数内で (暗黙的に)使用しない場合。

これはメンバー関数には当てはまりませんstatic- それはメンバー関数のポイントの一部ですstatic

[1]もちろん、コンパイラが関数のソース コードを「見る」ことができる場合、コンパイラは実際の関数をインライン化することを選択できます。thisポインタが使用されていない場合は、ポインタをインライン化プロセス。しかし、これも互換性を損なうものではありません。

于 2013-07-16T10:31:55.833 に答える