【问题标题】:Behaviour about const_cast<>关于 const_cast<> 的行为
【发布时间】:2013-03-16 04:35:18
【问题描述】:

我写了一个小问题来检查 const 数据成员上 const_cast 的行为。

using namespace std;


     class myString{
         public:
                 myString(char * str)
                 {
                         p=str;
                 }
                 const char * getString(){
                         return p;
                 }
         private:
                 const char *p;
 } ;


int main()
{
        char *p=(char*)malloc(8);
        cin>>p;
        myString *m= new myString(p);
        char *s =const_cast<char*>(m->getString());
        s[6]='y';
        cout<<s<<endl;
        return 0;
}

运行此程序后,我将输出为“yogendra”(一个 8 个字母的字符串)。我得到的输出是“yogendya” 现在我的怀疑。通过 const_cast 我们可以覆盖数据成员本身的行为,因为这里的字符串是 const char* 在转换之后我仍然可以修改它。

【问题讨论】:

  • 这是您通常应该编写代码以便不需要任何 const_cast 的原因之一。代码中多次出现 const_cast 表明应用程序的设计存在问题(尽管它也有有效的用途,但有时也无法避免)。
  • @PeterWood:除了没有为输入分配足够的内存之外,这里的未定义行为在哪里?可以修改const 对象,但本示例中没有const 对象。
  • @PeterWood 链接到标准? C++ 中的 AFAIK 抛弃 const 仅适用于多线程环境或不可变数据(例如文字)的 UD。手动添加 const 然后将其丢弃应该是无操作的(尽管几乎不合理)
  • @MikeSeymour Mea 过失

标签: c++ const-cast


【解决方案1】:

是的,您可以通过这种方式使用const_cast&lt;&gt;,它不会是未定义的行为,因为您的类中const char* 指向的对象确实是char* 类型的非常量。但小心点:。 C++ 标准。 §7.1.​5.1/4 说

除了可以修改任何声明为 mutable (7.1.1) 的类成员, 任何在 const 对象的生命周期 (3.8) 期间修改其结果的尝试 在未定义的行为中

const_cast 的安全使用是将 const 从 const 引用转换为非 const 对象:当存在非 const 对象并且您有 const ref 时,您可以安全地从 this 中转换 const

【讨论】:

  • 这个例子中没有 const 对象,所以没有未定义的行为(除了没有为输入分配足够的内存引起的)。
  • getString 返回 const char*
  • 确实;它返回一个指向非 const 对象的 const 指针。对象本身就是malloc分配的数组,不是const。
  • 所以这正是这个安全的例子,它是从 const char* 指针转换为 char 对象的,对吧?
  • @MikeSeymour: :) 感谢您澄清这一点。 malloc 返回的固有对象不是 const。该示例通过允许指向此对象的 指向 const 的指针将此返回的对象视为 const 对象,此外,此指针被强制转换以删除 const 性。由于原始对象不是 const 开始的,因此没有 UB。但是,如果原始对象确实是一个 const 对象,那么这将是一个 UB。所以关键是原始对象的 inherent 限定符而不是中间指针上的限定符。
【解决方案2】:

如果你说

char *s =const_cast<char*>(m->getString());

然后你基本上从指针中删除“const”,并声明你的s 是一个指向 char 的指针,它是一个可写的字符串。所以下一行

s[6]='y';

完全没问题。要保留 const,您应该将 s 声明为 const 指针

const char *s = m->getString();

在这种情况下,您将无法覆盖常量字符串(错误:分配只读位置)。我想这就是你想要的? const_cast 将简单地添加/删除 const 并在您的情况下将其删除。

【讨论】:

  • 感谢您的精彩解释,但是..如果我更改为 myString *m=new myString("yogendra");这里我传递了一个 const char *,当我运行这段代码时,我遇到了分段错误。
  • @YSBhai:在这种情况下,您正在尝试修改 const 对象(字符串文字)。这样做会产生未定义的行为;在您的情况下,该对象必须已放置在只读内存中,以便修改会导致错误。
  • @MikeSeymour:你打败了我 :)
  • @YSBhai:每个字符串文字,例如您的“yogendra”,都由编译器放置在只读内存中。您的 myString 类将该只读字符串的地址保存在 p 中,尝试使用 s[6]='y' 写入它会导致分段错误。要解决这个问题,请在 myString 类中创建字符串文字的副本以确保它是可写的。或者不要给它写信:)
【解决方案3】:

您已经准确地描述了 const_cast 的用途 - 它允许您从某些东西中删除 constness 并对其进行修改。由你决定不要滥用这种权力。 :-)

(在您的情况下,这不适用,但请注意,使用 const_cast 可能会导致崩溃 - 例如:

const char *c = "Hello";
char *s = const_cast<char*>(c);
s[0] = 'h';

可能会崩溃,因为编译器可以将字符串文字放入只读内存。)

【讨论】:

  • 值得注意的是,这只是实际上允许避免使用 const 的 C++ 类型转换,这是它的唯一目的。甚至 reinterpret_cast 都不允许。
猜你喜欢
  • 2011-04-17
  • 2014-06-06
  • 2011-11-13
  • 2019-10-14
  • 2014-01-03
  • 2013-09-23
  • 2011-08-23
  • 1970-01-01
  • 2016-10-09
相关资源
最近更新 更多