const_castは安全ですか?


92

に関する情報があまり見つかりませんconst_cast。(Stack Overflowで)私が見つけた唯一の情報は次のとおりです。

const_cast<>()/変数の削除CONST(ネス)(又は揮発性らしさ)を追加するために使用されます。

これは私を緊張させます。const_cast原因の予期しない動作を使用できますか?もしそうなら、何ですか?

または、いつ使用しても大丈夫const_castですか?


4
一番上の答えは、ひどく明白であるかもしれないけれども述べる価値のあるものを見落としています:定義済みの参照/ポインタを介して元のconstオブジェクトを変更しようとした場合にのみ、危険になりconstます。代わりに、const_castconst参照のみを受け入れ、constメソッドでのみ使用される、不十分な(または、私の場合は、遅延した)仕様のAPIを回避するだけの場合...まったく問題ありません。
underscore_d

1
@underscore_d:それをカバーする質問(および回答)のより正確なバージョン:実際に変更されない限り、constで定義されたオブジェクトにconstをキャストすることは許可されますか?
Peter Cordes

回答:


88

const_cast元々でなかった変数をキャストする場合にのみ安全ですconst。たとえば、のパラメータを取る関数がありconst char *、変更可能なを渡す場合char *const_castそのパラメータをに戻しchar *、変更しても安全です。ただし、元の変数が実際constにだった場合、使用const_castすると未定義の動作が発生します。

void func(const char *param, size_t sz, bool modify)
{
    if(modify)
        strncpy(const_cast<char *>(param), sz, "new string");
    printf("param: %s\n", param);
}

...

char buffer[16];
const char *unmodifiable = "string constant";
func(buffer, sizeof(buffer), true);  // OK
func(unmodifiable, strlen(unmodifiable), false); // OK
func(unmodifiable, strlen(unmodifiable), true);  // UNDEFINED BEHAVIOR

9
それは真実ではない。C ++標準。§7.1.​5.1/4 says Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior どんな試みでも!元の変数についての言葉はありません。
Alexey Malistov、2010年

20
@Alexey:元の変数は、ポイントまたは参照されるものに関するものです。非constオブジェクトへのconst参照を取得できます。したがって、参照先オブジェクトは実際にはconstではないため、書き込み可能な参照へのキャストは明確に定義された動作です。
パピー

43
@Alexey Malistov:いいえ。「オブジェクト」とは、メモリに占有されている実際のストレージ領域を指します(§1.7)。非constオブジェクトへのconst参照を取得しても、オブジェクトはconstになりません。const 参照パラメーター(constポインターパラメーターではない)の場合のみ、コンパイラーは暗黙的にコピーを作成できます(§5.2.2/ 5)。これはここでは当てはまりません。
Adam Rosenfield

8
「しかし、元の変数が実際にconstだった場合、const_castを使用すると、未定義の動作が発生します」このステートメントは誤りです。
オービットのライトネスレース

7
最初に宣言されたものから削除するために使用するの UBではありません。しかし、そのオブジェクトに実際に書き込もうとするの UBです。あなたが読んだだけで大丈夫で、それ自体はUBを引き起こしません。それは恐ろしい考えですが、本質的にUBではありません。const_castconstconstconst_cast
Jesper Juhl、

35

const_castが安全で便利な2つの状況を考えることができます(他にも有効なケースがあるかもしれません)。

1つは、constインスタンス、参照、またはポインターがあり、constが正しくないAPIにポインターまたは参照を渡したいが、CERTAINがオブジェクトを変更しない場合です。ポインターをconst_castしてAPIに渡すと、実際には何も変更されません。例えば:

void log(char* text);   // Won't change text -- just const-incorrect

void my_func(const std::string& message)
{
    log(const_cast<char*>(&message.c_str()));
}

もう1つは、「可変」を実装していない古いコンパイラーを使用していて、論理的には定数であるがビット単位の定数ではないクラスを作成する場合です。constメソッド内で 'this'をconst_castして、クラスのメンバーを変更できます。

class MyClass
{
    char cached_data[10000]; // should be mutable
    bool cache_dirty;        // should also be mutable

  public:

    char getData(int index) const
    {
        if (cache_dirty)
        {
          MyClass* thisptr = const_cast<MyClass*>(this);
          update_cache(thisptr->cached_data);
        }
        return cached_data[index];
    }
};

これは...この質問に答えていないようです。彼はconst_cast、それがどのように役立つのかではなく、未定義の動作を引き起こす可能性があるかどうか尋ねました
Michael Mrozek

13
質問から:「代わりに、いつconst_castを使用してもよいですか?」
Fred Larson

「いつ未定義でないか」のように; 彼はそれが有用であるときの例を探していません
Michael Mrozek '21

質問の手紙だけに固執することができます。これに基づいて、の例示的な使用の提示はconst_cast有効な答えです。he質問だけが主題なので、質問はありません。
TruthAdjuster

24

それがconst_castについて見つけられる唯一の情報であるとは信じがたいです。2番目のGoogleヒットからの引用:

constとして明示的に宣言されているオブジェクトのconstnessをキャストして変更しようとすると、結果は定義されません。

ただし、constとして明示的に宣言されていないオブジェクトのconstnessをキャストする場合は、安全に変更できます。


Grrrreaatの回答。これをこの回答と組み合わせると、全体像がわかります。
bobobobo 2011

うーん。あなたの答えの2番目のステートメントに関して、最初にconstとして明示的に宣言されなかったオブジェクトの「const」ネスはどのようにあるのか尋ねてもいいですか。
hAcKnRoCk 2012

非constオブジェクトをconstにする多くの方法があります、@ Iam。たとえば、オブジェクトをconst-referenceパラメータとして渡します。または、const-to-constに割り当てます。またはを使用しますconst_cast。または、その上でconstメソッドを呼び出します。
ロブ・ケネディ

12

アダムが言うこと。const_castが役立つ別の例:

struct sample {
    T& getT() { 
        return const_cast<T&>(static_cast<const sample*>(this)->getT()); 
    }

    const T& getT() const { 
       /* possibly much code here */
       return t; 
    }

    T t;
};

私たちは、第一種へのconstを追加しthis、その後、我々はのconstのバージョンを呼び出すにポイントgetTして、私たちは以来、有効な戻り値の型からのconstを削除するtそれ以外の非constバージョンは(非constでなければならないgetTことができませんでした呼ばれた)。これは、大きな関数本体があり、冗長なコードを避けたい場合に非常に役立ちます。


3
私はむしろ、constnessを追加するために静的キャストを使用します:static_cast <const sample *>(this)。私がconst_castを読んでいるとき、それはコードが潜在的に危険なことをしていることを意味するので、可能な限り使用しないようにします。
mfazekas 2009年

1
右、最初はstatic_cast、または暗黙のキャスト(ブーストの)にすることもできます。静的キャストを使用して修正します。感謝
ヨハネスシャウブ-litb 2009年

3
私がいるかどうかに行き来const_castまたはstatic_castより良いです。const_castあなたがしたいことだけができます:cv-qualifiersを変更してください。static_cast意図しない他の操作を「サイレント」で実行できます。ただし、最初のキャストは完全に安全であり、static_castより安全である傾向がありますconst_cast。これはconst_castあなたの意図をよりよく伝えますが、static_castあなたの行動の安全性をよりよく伝えている状況だと思います。
David Stone

10

短い答えはノーです、それは安全ではありません。

長い答えは、あなたがそれを使うのに十分知っているなら、それは安全であるべきだということです。

キャストしているとき、本質的に言っているのは、「コンパイラーが知らないことを知っています」ということです。const_castの場合、あなたが言っていることは、「このメソッドは非const参照またはポインターを取り込んでも、渡すパラメーターを変更しないことはわかっています。」

したがって、キャストを使用して知っていると主張していることを実際に知っている場合は、それを使用しても問題ありません。


5

コンパイラがconstであると考えていたものを変更し始めた場合、スレッドセーフでチャンスを破壊しています。


1
何?不変(const)オブジェクトがある場合、それらをスレッド間で簡単に共有できます。コードの一部がconst-nessを捨てる瞬間、スレッドの安全性がすべて失われます!なぜ私はこれのためにダウンモッドですか? ため息
Matt Cruikshank、

8
Constは確かにコードをスレッドセーフにするのに役立つツールですが、保証はありません(コンパイル時の定数の場合を除く)。2つの例:constオブジェクトには変更可能なメンバーが含まれる場合があり、オブジェクトへのconstポインターを使用しても、オブジェクト自体が変更されているかどうかについては何もわかりません。
James Hopkin、

コンパイラオプティマイザの言葉の使用における信頼とセキュリティの感情については考えていなかったので、これは良い答えだと思いますconstconst信頼です。const_castその信頼を破っています:(
bobobobo

1
変更可能でスレッドセーフについて:channel9.msdn.com/posts/…–
MFH

-3
#include <iostream>
using namespace std;

void f(int* p) {
  cout << *p << endl;
}

int main(void) {
  const int a = 10;
  const int* b = &a;

  // Function f() expects int*, not const int*
  //   f(b);
  int* c = const_cast<int*>(b);
  f(c);

  // Lvalue is const
  //  *b = 20;

  // Undefined behavior
  //  *c = 30;

  int a1 = 40;
  const int* b1 = &a1;
  int* c1 = const_cast<int*>(b1);

  // Integer a1, the object referred to by c1, has
  // not been declared const
  *c1 = 50;

  return 0;
}

ソース:http : //publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fkeyword_const_cast.htm


スパムリンクによる反対投票
TruthAdjuster
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.