【问题标题】:How to pointer-cast Foo** to const Foo** in C++如何在 C++ 中将 Foo** 指针转换为 const Foo**
【发布时间】:2009-08-20 21:20:47
【问题描述】:

我有

class Fred 
{
public:
  void inspect() const {}; 
  void modify(){};
};

int main()
{
 const Fred x = Fred();
 Fred* p1;
 const Fred** q1 = reinterpret_cast<const Fred**>(&p1);
 *q1 = &x; 
 p1->inspect();
 p1->modify();
}

怎么可能做到 常量弗雷德** q1 = &p1 通过指针转换?

(我刚刚读到这可能是可能的)

感谢您的回答。 const_cast 确实适用于对象

#include <iostream>
#include <stdio.h>
using namespace std;

class Fred 
{
 int a;

public:
Fred(){};
Fred(int a_input)
{
 a = a_input;
};

void inspect() const 
{
 cout << "Inspect called"<< endl;
 cout << "Value is ";
 cout << a << endl;
}; 

void modify()
{
 cout << "Modify called" << endl;
 a++;
};

};

int main()
{
 const Fred x = Fred(7);
 const Fred* q1 = &x;
 Fred* p1 = const_cast<Fred*>(q1); 
 p1->inspect();
 p1->modify();
 p1->inspect();
 x.inspect();
 *p1 = Fred(10);
 p1->inspect();
}

给予

Inspect called
Value is 7
Modify called
Inspect called
Value is 8
Inspect called
Value is 8
Inspect called
Value is 10
Inspect called
Value is 10

但是,对于预定义的类型,它不起作用:

int main()
{
 const double a1 = 1.2;
 const double* b1 = &a1;
 cout << "a1 is " << (*b1) << endl;
 cout << "b1 is " << b1 << endl;
 double* c1 = const_cast<double*>(&a1);
 cout << "b1 is " << b1 << endl;
 cout << "c1 is " << c1 << endl;

 double* d1 = static_cast<double*>(static_cast<void*>(c1));
 cout << "d1 is " << d1 << endl;
 cout<< "*d1 is " << *d1 << endl;

 *d1=7.3;

 cout<< "*d1 is " << *d1 << endl;
 cout<< "*d1 address is "<< d1 << endl;
 cout << "a1 is " << a1 << endl;
 cout << "a1 address is" << &a1 << endl;
 cout<< "*d1 is " << *d1 << endl;
 cout<< "*d1 address is "<< d1 << endl;

 double f1=a1;
 printf("f1 is %f \n", f1);
}

导致:

a1 is 1.2
b1 is 0xffbff208
b1 is 0xffbff208
c1 is 0xffbff208
d1 is 0xffbff208
*d1 is 1.2
*d1 is 7.3
*d1 address is 0xffbff208
a1 is 1.2
a1 address is0xffbff208
*d1 is 7.3
*d1 address is 0xffbff208
f1 is 1.200000 

显然,g++ 编译器进行了优化,以便在找到 a1 时将其替换为 1.2,因此,即使它在堆栈上的值已更改,它也不在乎。

(在我的情况下,我在直接读取 *b1、*c1 时遇到了问题,因此我必须进行双重静态转换——重新解释转换不起作用)。

有没有办法真正改变a1,“正常”编译,因此没有优化就不能编译(所以我超越了优化效果)?

【问题讨论】:

  • 感谢重新格式化!更容易阅读!
  • 您添加的新信息实际上是一个不同的问题。将来考虑将其发布(它也会以这种方式获得更多答案)。至于 const 原语的编译器优化:如果您不希望编译器对其进行优化,嗯...不要将其设为 const。 const 的目的是告诉编译器您不会更改该值。因此,如果您事后尝试对其进行更改,则违反了 C++ 标准。换句话说,不要这样做!再一次,如果您打算更改一个值,请不要将其设为 const。期间。

标签: c++ pointers casting


【解决方案1】:

应该这样做:

Foo** f;
const Foo** cf = const_cast<const Foo**>(f);

【讨论】:

    【解决方案2】:

    这不是一个好主意,因为它违反了类型安全。让我解释一下原因:

    Fred* pFred;
    const Fred** ppFred = const_cast<const Fred**>(&p);
    
    *ppFred = new const Fred;  // Now pFred points to a const Fred
    
    pFred->some_evil_mutating_method(); // can do, since type of *pFred is non-const!
    

    【讨论】:

    • 您警告远离此类行为是正确的,但请不要将“不是一个好主意”误认为“不可能”。在他的代码中用 const_cast 替换 reinterpret_cast 会产生完全有效、可编译的 C++。
    • 是的,刚刚检查了标准。我的错 - 我从来没有意识到 const_cast 是专门为指针链定义的,尽管它本质上是不安全的。具有讽刺意味的是,考虑到通常认为 const_cast 仅在您从本质上是 const 的对象中抛弃 const 时才不安全 - 而在这种情况下,当您将 const “添加”到非 const 对象时是不安全的.对我来说,这看起来像是一个非常糟糕的设计决定,但我想这对你来说是 C++。将修复答案。
    • @Pavel,如果你需要一个 const_cast,你正在做一些有潜在危险的事情,安全案例不需要演员表。 (请注意,在 C 中,存在需要强制转换的安全案例)。
    • 这不是真的。例如,您可能需要 const_cast 来调用 const 重载或 const 成员方法,否则您将获得非 const 版本。这是非常安全的,甚至没有潜在的危险。
    • 我的印象是 Pavel 非常了解该原则,他只是向 OP 表达了这一点。
    【解决方案3】:

    你想要const_cast。

    【讨论】:

    • 允许您创建指向 const 对象的非 const 指针,但任何实际更改该 const 对象的尝试仍会导致未定义的行为。
    【解决方案4】:

    你为什么不直接做:?

    const Fred** q1;
    *q1 = p1;
    

    或者你想在没有 const_cast 的情况下避免 constness 违规? -- 不,先生,您不能。

    【讨论】:

      【解决方案5】:

      你不应该这样做。您无法轻松进行转换的事实是因为它破坏了恒定的正确性(并且您的代码会对其进行练习)。使用上面的建议,您的代码将编译并调用常量对象的变异方法(最后一行代码)。

      不推荐这样做,在极少数情况下甚至可能会杀死您的应用程序(一个常量全局对象可以存储在只读内存页面中),或者使其处于不稳定状态(您可以通过以下方式更改对象的内部状态)通过常量引用更改为内部成员元素,破坏对象不变量)。

      关于您的问题:C++ FAQ Lite [18.17]

      【讨论】:

        【解决方案6】:

        您不需要对const Fred** q1 = &amp;p1 进行任何转换,因为可以在其声明中将非常量Fred** 直接分配给const Fred** q1。

        【讨论】:

        • 不,它不能。自己尝试一下 - 如果没有 const_cast,它将无法编译。
        猜你喜欢
        • 1970-01-01
        • 2011-01-18
        • 2022-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多