2

「Effective C++、Second Edition」という本を読んでいます。その本では、const メンバー関数と、ビットごとの const ネスと概念的な const ネスについて説明しています。

ほとんどのコンパイラはビット単位の const-ness を使用すると言われています。つまり、const メンバー関数内のオブジェクトのデータ メンバーを変更することはできません。

次に、const テストでビットごとに動作しないように見えるメンバー関数の例があります。

こんなふうになります:

#include "stdafx.h"
#include <string>
#include <iostream.h>

using namespace std;

class mystring
{

public:
    mystring(const char* value);

    operator char *() const { return data; }

private:
    char * data;
};

mystring::mystring(const char * value)
{

    mystring::data = const_cast<char*>(value);
}


int main(int argc, char* argv[])
{
    const mystring s = "Hello";

    char * nasty = s;

    *nasty = 'M';

    printf("s: %c", s);

    return 0;
}

これを実行すると、私の本では、 の値を変更できるようにする必要があると書かれてsいますconst。これは、char* データがconst char*値と同じものを指しているためです。 *dataこの場合はございませんconst

ただし、これを MS VC++ 6.0 で実行しようとすると、次の行でアクセス違反が発生します。 *nasty = 'M';

誰かが何が起こっているのか説明できますか? 私は何かを逃したと思いますか?

私には const があるのでmystring s、それを変更することはできないように思えますが、本に書かれていることはぎこちないようです。

4

4 に答える 4

7

アクセス違反は、文字列リテラルを変更しようとしたために発生します。あなたのコードは以下と同等です:

char * p = "Hello";
* p = 'M';

これは C と C++ の両方で違法です - const メンバー関数とは関係ありません。

于 2010-07-02T11:48:45.837 に答える
2

char*ポインターが文字列リテラルを指しているためにのみ、アクセス違反が発生します。文字列リテラルの変更は未定義の動作 (あなたの場合は AV) であり、const-correctness とは関係ありません。

于 2010-07-02T11:49:47.320 に答える
0

あなたがしていることは未定義の動作です。const-ness を捨てて、定数値を変更しようとしています。その例が本からそのままコピーされた場合、その本は間違っています。

合法的なのはconst_cast<>、非定数オブジェクトへの定数ポインタ/参照から const 性をキャストすることです。

int i = 5;
int const & ir = i;
const_cast<int&>(ir) = 7; // valid
int const * ip = &i;
*const_cast<int*>(ip) = 9; // valid

const int c = 11;
int const & cr = c;
const_cast<int&>(cr) = 13; // Undefined behavior

実際の const オブジェクトへの参照から const 性をキャストできない理由は、コンパイラがオブジェクトを読み取り専用メモリに配置することを決定できるためです。変化...)

于 2010-07-02T11:55:21.643 に答える
0

あなたの例では、変更しません。sメンバー変数がs指すメモリを変更しようとします。は多くの場所に配置できるconstため、実際に宣言する内容には注意が必要ですconst

メンバー関数operator char*() constはメンバー変数を変更できません。試してみるoperator char *() const { data = "something else"; return data; }と、コンパイラは変更が許可されていないことを通知しますdata。ただし、この場合はdata変更せずにそのまま戻してください。それは許可されています。dataのように、ポイント先のメモリを変更することもできますoperator char *() const { *data = 'M'; return data; }。ただし、data変更が許可されていない文字列リテラルを指しているため、これはコンテキストでは失敗します。

于 2010-07-02T12:05:39.433 に答える