20

C ++では、スタック割り当てオブジェクトを宣言できますconst

const Class object;

その後、そのようなオブジェクトで非constメソッドを呼び出そうとすると、未定義の動作になります。

const_cast<Class*>( &object )->NonConstMethod(); //UB

ヒープに割り当てられたオブジェクトがconst同じ結果になる可能性はありますか?つまり、次の可能性があります。

const Class* object = new Class();
const_cast<Class*>( object )->NonConstMethod(); // can this be UB?

未定義動作でもありますか?

4

6 に答える 6

20

はい。constヒープ オブジェクトの構築と破棄は合法です。他のconstオブジェクトと同様に、それを非constオブジェクトとして操作した結果 (たとえばconst_cast、ポインターまたは参照の を介して) は、未定義の動作を引き起こします。

struct C
{
        C();
        ~C();
};

int main()
{
        const C* const p = new const C;

        C* const q = const_cast<C*>(p); // OK, but writes through q cause UB

        // ...

        delete p; // valid, it doesn't matter that p and *p are const

        return 0;
}
于 2009-12-18T11:08:00.317 に答える
11

ヒープの例でnewは、non-constへのポインタを返します。constへのポインターに格納した(そしてconst_castnon-constへのポインターに戻した)という事実は、オブジェクト自体がスタックに割り当てられたものと同じようにconstではないという事実を変更しませんは。

ただし、ヒープ上にconstオブジェクトを作成できます。

const Class* object = new const Class();

このような場合、non-constへのポインターへのキャストと、non-constメソッドの呼び出しは、constスタック割り当てオブジェクトと同じ状況になります。

(ヒープ上にconstオブジェクトを作成するというアイデアは私にとって新しいものでした。これまで見たことがありませんでした。チャールズ・ベイリーに感謝します。)

于 2009-12-18T10:50:52.253 に答える
2

はい、ヒープ割り当てオブジェクトは const にすることができます。7.1.5.1/5 の例からの抜粋を考えてみましょう。

const int* ciq = new const int (3);    // initialized as required
int* iq = const_cast<int*>(ciq);       // cast required
*iq = 4;                               // undefined: modifies a const object

newconst オブジェクトの作成を求めていないため、質問で示した例は問題ありません。結果をconstへのポインタに格納しているだけです。

于 2009-12-18T11:23:48.723 に答える
1

明らかに:

struct Foo {
  const int Bar;
  Foo() : Bar(42) { }
};

Foo* foo = new Foo;
const_cast<int&>(foo->Bar); // don't do this.
于 2009-12-18T11:22:41.190 に答える
1

変更可能なメンバーを忘れないでください

mutableNonConstMethodが const 修飾クラスの修飾メンバー (7.1.5.1 (4) を参照)のみを変更する場合、未定義の動作にはなりません。はい、それ以外の場合は未定義の動作です。

const A* p = new(const A);
A *q = const_cast<A*>(p);
q->NonConstMethodThatModifiesMembers();             // undefined behaviour!
q->NonConstMethodThatOnlyModifiesMutableMembers();  // defined behaviour!
于 2009-12-18T12:03:07.537 に答える
0

const_cast は、オブジェクトが実際には読み取り専用である場合に UB を引き起こす可能性があります (たとえば、コードでハードコードされた文字列を使用する場合、コンパイラは、読み取り専用の特定のメモリ領域に配置することにより、そのようなオブジェクトを作成できます)。これは、参照 (const ポインター、const 参照など) を保持する方法に関係なく、ヒープ割り当てオブジェクトでは発生しません。

于 2009-12-18T11:29:53.877 に答える