constオブジェクト(C++11では7.1.6.1/4)を変更する(しようとする)のは未定義の動作です。
したがって、重要な質問は、constオブジェクトとは何であり、m_x
1つであるかということです。もしそうなら、あなたはUBを持っています。そうでない場合は、UBであることを示すものは何もありません。もちろん、ここに示されていない他の理由(データ競合など)でUBである可能性があります。
関数f
がクラスのconstインスタンスで呼び出された場合C
、m_x
はconstオブジェクトであるため、動作は未定義です(7.1.6.1/5)。
const C c;
c.f(); // UB
関数f
がクラスの非constインスタンスで呼び出された場合C
、m_x
はconstオブジェクトではないため、動作は私たちが知る限り定義されています。
C c;
const C *ptr = &c;
c->f(); // OK
したがって、この関数を作成する場合は、constインスタンスを作成しC
て関数を呼び出さないように、ユーザーに翻弄されます。おそらく、のインスタンスはC
一部のファクトリによってのみ作成されます。その場合、それを防ぐことができます。
完全なオブジェクトがである場合でもデータメンバーを変更可能にする場合はconst
、それをマークする必要がありますmutable
。それが目的であり、のconstインスタンスで呼び出されたmutable
場合でも、定義された動作を提供します。f
C
C ++ 11以降、const
メンバー関数とmutable
データメンバーの操作はスレッドセーフである必要があります。そうしないと、タイプが標準ライブラリの関数およびコンテナで使用されている場合に、標準ライブラリによって提供される保証に違反します。
したがって、C ++ 11ではm_x
、アトミックタイプを作成するか、他の方法で変更を同期するか、constとマークされていても、関数f
がスレッドセーフではないという最後の手段としてドキュメントを作成する必要があります。これらのことを何もしなかった場合は、ユーザーが機能するはずであると合理的に信じているが実際にはUBを持っているコードを書く機会を再び作成します。