正确使用const_cast <>

作为一个常见的规则,在C ++代码中使用const_cast<>()通常被认为是不好的做法,因为它在大多数情况下显示了devise中的一个缺陷。

虽然我完全同意这一点,但是我不知道使用const_cast<>()是否正确,是唯一的解决scheme

你们能给我举一些你知道/遇到的例子吗?

非常感谢你。

const_cast也被用来删除volatile修饰符,正如这个(有争议的)文章中的实践:

http://www.drdobbs.com/184403766

它被devise得非常多,只能用于传统的API,而不是常量正确的,即使用一个函数,你不能改变它有非const接口,但实际上并没有改变接口上的任何东西

像其他人所说,其主要目的是从对象中删除const ,以传递给非const的正确的函数,你知道不会修改参数。

有一个技巧(通过Meyers?)避免代码重复,它是这样的:

 struct foo { const return_type& get(void) const { // fancy pants code that you definitely // don't want to repeat return theValue; // and got it } return_type& get(void) { // well-defined: Add const to *this, // call the const version, then // const-cast to remove const (because // *this is non-const, this is ok) return const_cast<return_type&>(static_cast<const foo&>(*this).get()); } }; 

我同意你的说法,正常使用是因为你需要隐藏一个“devise缺陷”。

当您尝试将C ++接口到现有的C代码时,IME是典型的使用场景之一。 很多现有的C代码都将Cstring作为char *即使string未被修改,而通常也被表示为在C ++中转换为const char *东西。 这是你通常使用const_cast解决的两种语言之间的阻抗不匹配问题。 当然,你最好确定你正在接口的代码没有得到任何关于修改正在传入的数据的可爱想法。

我会说,这是一个代码在新编写的代码中的味道,但与旧的C和C ++代码接口,这是一个必要的邪恶。 也就是说,对于那些需要const_cast来处理任何非POD对象的代码,我会非常谨慎,因为这通常是在devise级而不是代码级应该解决的问题。

一个合法的用法(在我看来)是std::set迭代器。 它们总是const ,以防止更改集合中使用的密钥。 更改密钥会破坏该组的内部结构并导致未定义的行为。

但是,只要不改变密钥就可以安全地更改对象中的其他数据。

假设你有一个std::set如下所示:

 std::set<MyObject> some_set; 

而像这样的一堂课:

 class MyObject { public: MyObject(const std::string &key) : key_(key) {} bool operator<(const MyObject &other) const { return key_ < other.key_; } private: // ... // <some other data> // ... const std::string key_; }; 

在上面的例子中, 键已经是const了 ,所以即使你修改了这个对象,也不能破坏这个集合的内部结构。

通常你只能从一个集合迭代器中获得一个const引用:

 const MyObject &object = *some_set_iterator; 

但是由于键是const ,因此const_cast解引用的迭代器是安全的:

 MyObject &object = const_cast<MyObject &>(*some_set_iterator); 

这样做的一个非常合理的用法是当你有一个const和非常量api(分别为const和非const对象)

 class Bar { const SomeType& foo() const; SomeType& foo(); } 

那么因为我们不想在我们经常使用的两个函数中复制代码

 class Bar { SomeType& foo() { //Actual implementation } const SomeType& foo() const { return const_cast<Bar*>(this)->foo(); } }; 

这当然假设foo不会做违反const语义的事情。

是的,当然,当你的调用代码,你不能修改,而不是正确的。 应该指出的是,你只能用它来调用函数,你知道肯定不会修改你的数据!