这是const_cast的有效用法吗?

时间:2015-04-20 18:51:18

标签: c++ const const-cast

在示例代码中,调用message()永远不会影响该类的内容,因此我希望该方法为const。但我不希望返回值也为const,因此使用const_cast如下安全吗?还是有更好的解决方案?

编辑:抱歉..所以n_是一个指针!

EDIT2:我终于设法正确地重新产生了问题。如果n_int n[100]中的数组,该怎么办?然后我看到没有const_cast的问题。

class A
{
private:
    int n_[10];

public:
    /* ... */

    int* n() const
    {
        return const_cast<int*>(n_);
    }
};

5 个答案:

答案 0 :(得分:7)

返回类型(不是引用)将生成您要返回的对象的副本。因此无需投射,可以在不影响原件的情况下更改副本。如果删除const_cast,则代码将完全编译。

编辑:根据问题的最新修改,我会说这是对const_cast的滥用。 C ++遵循的原则是const成员函数不仅不应对对象本身进行任何更改,而且不应返回可用于在函数外部进行更改的任何内容。通过将非const指针返回到成员变量,您违反了这一原则。

答案 1 :(得分:5)

不,这不是const_cast的有效用法。

您的函数未修改数组,但它授予将数组修改为调用者的权限。因此,它应该拥有这些权利。您无法让某人访问您自己无法访问的内容。因此该方法不应该是const,因此不需要const cast。

您可能还需要函数的const版本,它返回const int*。这与例如std::vector::operator[]的原理相同。即使操作符不修改向量,它也会授予访问权限以修改向量,因此它不是const函数。 (但是还有一个const重载版本,它返回一个const引用,因此不授予修改向量的权利)

答案 2 :(得分:0)

您可以返回n_,因为它是

int n() const
{
    return n_;
}

答案 3 :(得分:0)

无需使用演员阵容。在该函数中,this->n_是一个const指针,它不指向const int

int* n() const
{
    // No need for a cast.
    return n_;
}

const int*函数返回const更有意义。你不想要这样的东西:

const A a;
a.n()[0] = 10;

这颠覆了对象的const - ness。您可以使用以下命令来阻止:

const int* n() const
{
    // No need for a cast either.
    return n_;
}

答案 4 :(得分:0)

一般来说,将T const投放到Tconst_cast<>几乎总是不必要的。这是因为常量对象被转换为非常量临时对象,这可以在没有强制转换的情况下安全地完成。

int const n;   // n is a constant int
int x = n;     // perfectly safe

即使T是指针类型,也是如此。

int * const n; // n is a constant pointer to an int
int * x = n;   // perfectly safe

但是,如果将const关键字移到前面,它不再使指针类型保持不变,而是指向常量的类型。因此,对于我们上面的例子:

const int * n; // n is a pointer to a constant int
int * x = n    // error, x is a pointer to an int

您可以看到x指向的内容与n指向的内容不同,因此初始化将失败。在这种情况下,初始化需要const_cast<>

int * x = const_cast<int *>(n);
               // cast away the const-ness that n is pointing to

如果您知道n实际上是可修改的(如果指针指向实际的只读内存可能不是这样),或者如果您知道x的用户,则应该这样做实际上不会尝试修改n指向的内容。


对于您的示例,您似乎相信您的const方法应返回指向对象所持数据的指针,以便调用者可以修改数据。也就是说,由于n()方法被声明为const,这意味着被访问对象的内容应该被认为是常量。因此,n_是一个常量int的数组,它将衰减为指向常量int的指针,但是您想要返回指向int的指针。

如果您希望n_可以修改,无论该对象是否被视为常量,您都可以使用mutable声明该意图。即使包含的对象为n_,这也会使const被视为非常量,因此不需要const_cast

class A
{
private:
    mutable int n_[10];

public:
    /* ... */

    int* n() const
    {
        return n_;
    }
};