4

const の正確性を考慮せずに記述されたコードがいくつかあります。これを変更する状況はありますか

class X
{
public:
    X(X& rhs); // does not modify rhs
    ...
};

これに

class X
{
public:
    X(const X& rhs);
    ...
};

既存のプログラムの動作を変更しますか? この変更により、現在コンパイルされていないコードをコンパイルできるようになることはわかっていますが、既にコンパイルされているコードが動作を変更する状況があるかどうかに興味があります。

同様の質問ですが、代わりにこの変更を行うメリットはありますか?

class X
{
public:
    X(X& rhs); // does not modify rhs
    X(const X& rhs);
    ...
};
4

4 に答える 4

2

コピーコンストラクターについては、そうは思いません。ただし、一般に、の宣言constは呼び出されるメソッドに影響を与える可能性があることに注意してください。頭に浮かぶ唯一の例は、配列のオーバーロードです。たとえば、この質問を参照してください。

于 2013-04-22T12:47:05.433 に答える
1

実際、コピーコンストラクターは、常に引数として const 参照を取る必要があります。

X(X& rhs) { } // does not modify rhs

これは const オブジェクトのコピーを許可しないため、次のコードはコンパイルされません。非 const オブジェクトは const 引数として機能できますが、その逆は不可能です

X const test;
X new_x(test);

誰かが const オブジェクトのコピーを排除する必要がある理由を想像できません。

行いたい変更について: コピー コンストラクターは、非 const で定義された X メンバー関数に依存していますか?

これは魅力のように機能しますが、const オブジェクトのコピーを許可します。

class X
{
private:
  int a;
public:
  X(X &rhs) { a = rhs.value(); } 
  int& value (void) { return a; }
};

rhs次の例は、 const であるが const ではないため、コンパイルされませvalue()ん。

class X
{
private:
  int a;
public:
  X(X const &rhs) { a = rhs.value(); } 
  int& value (void) { return a; }
};

クラス const を正しくしたい場合は、おそらくクラス全体を調べる必要があります。クラス内の実装にのみ影響するはずです。外部コードがクラスメンバー関数の「非定数性」に依存する必要があるケースがわからないためです。私の例のように、パブリックメンバー関数によって非定数参照が返される場合を除きます。

次のスニペットは意図したとおりに機能します。

class X
{
private:
  int a;
public:
  X(int const &b) : a(b) { }
  X(X const &rhs) { a = rhs.value(); } 
  int const & value (void) const { return a; }
};

ただし、これは次のようなコードに干渉することに注意してください。

X test(100);
test.value() = 12;

これは を使用しても機能しますint& value (void) { return a; } が、 では失敗しint const & value (void) const { return a; }ます。もちろん、安全のために両方を提供することもできます。

于 2013-04-22T13:19:29.500 に答える
0

ジェクリンは彼の答えで重要な点を指摘していますが、やや不明確なので、よりよく説明しようと思います。

オブジェクトまたは参照の constness は、オーバーロードの解決に影響します。たとえばconst、メンバー関数のベース オーバーロードを持つオブジェクトがある場合、さまざまなオーバーロードが選択されます。

struct foo {
    void do_stuff();
    void do_stuff() const;
};

int main() {
    foo f;
    const foo& fr = f;

    f.do_stuff();   // calls non-const version
    fr.do_stuff();  // calls const version
}

ここで、オーバーロードの 1 つに副作用があり、もう 1 つにはない副作用がある場合、署名を変更すると、プログラムが正常にコンパイルされると (またはむしろ)、異なる動作が得られます

于 2013-04-22T13:52:27.727 に答える
0

コピー コンストラクターを持つクラスを変更しているため、コピー コンストラクターのコードを検査できると想定しています。この変更を行うことができ、コピー コンストラクターでコンパイラ エラーが発生しない場合は、おそらく問題ありません。考慮すべき 1 つの conor ケースは、特に最適化されたコードで呼び出される保証がないため、コピー代入演算子が行うことです。そのため、コピーの割り当てが const パラメーターで機能することも確認してください。

于 2013-04-22T12:44:28.893 に答える