这是 const_cast 的有效用法吗?
Is this a valid use of const_cast?
在示例代码中,调用message()
不会影响class的内容,所以我希望方法是const
。但是我不希望 return 的值也为 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_);
}
};
返回一个类型(不是引用)将复制您正在return的对象。因此不需要施放它,可以在不影响原件的情况下更改副本。如果删除 const_cast
.
代码将编译干净
编辑:根据对问题的最新编辑,我认为这是对 const_cast
的滥用。 C++ 遵循的原则是 const
成员函数不仅不应对对象本身进行任何更改,而且不应 return 任何可用于在函数外部进行更改的内容。通过 return 指向成员变量的非常量指针,你违反了这个原则。
你可以 return n_
,就这样
int n() const
{
return n_;
}
不需要使用强制转换。在函数中,this->n_
是一个 const
指针,它不指向 const int
.
int* n() const
{
// No need for a cast.
return n_;
}
从 const
函数中 return 一个 const int*
更有意义。你不想要这样的东西:
const A a;
a.n()[0] = 10;
这颠覆了对象的 const
-ness。您可以使用以下方法来防止这种情况:
const int* n() const
{
// No need for a cast either.
return n_;
}
不,这不是 const_cast
的有效用法。
您的函数不是在修改数组,而是将修改数组的权限授予调用者。因此,它本身应该拥有这些权利。您不能授予某人访问您自己无权访问的内容的权限。所以这个方法不应该是const,const转换就没有必要了。
您可能还需要函数的 const 版本,returns 和 const int*
。这与 std::vector::operator[]
等的原理相同。即使运算符不修改向量,它也授予修改向量的权限,因此它不是 const 函数。 (但还有一个 const 重载版本,returns 一个 const 引用,因此不授予修改 vector 的权利)
一般来说,用 const_cast<>
将 T const
转换为 T
几乎总是不必要的。这是因为常量对象正在转换为非常量临时对象,无需强制转换即可安全地完成此操作。
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
实际上是可修改的(如果指针指向实际的只读内存,则可能不是),或者如果您知道 [=20] 的用户=]实际上不会尝试修改n
.
指向的内容
对于您的示例,您似乎认为您的 const
方法应该 return 指向对象所持有数据的指针,以便调用者可以修改数据。也就是说,由于 n()
方法被声明为 const
,这意味着被访问的对象的内容应该被认为是常量。因此,n_
是常量 int
的数组,它将衰减为指向常量 int
的指针,但您希望 return 指向 int
的指针。
如果您希望 n_
可修改,无论对象是否被视为常量,您可以使用 mutable
声明该意图。这将使 n_
被视为非常量,即使包含对象是 const
,因此 const_cast
变得不必要。
class A
{
private:
mutable int n_[10];
public:
/* ... */
int* n() const
{
return n_;
}
};
在示例代码中,调用message()
不会影响class的内容,所以我希望方法是const
。但是我不希望 return 的值也为 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_);
}
};
返回一个类型(不是引用)将复制您正在return的对象。因此不需要施放它,可以在不影响原件的情况下更改副本。如果删除 const_cast
.
编辑:根据对问题的最新编辑,我认为这是对 const_cast
的滥用。 C++ 遵循的原则是 const
成员函数不仅不应对对象本身进行任何更改,而且不应 return 任何可用于在函数外部进行更改的内容。通过 return 指向成员变量的非常量指针,你违反了这个原则。
你可以 return n_
,就这样
int n() const
{
return n_;
}
不需要使用强制转换。在函数中,this->n_
是一个 const
指针,它不指向 const int
.
int* n() const
{
// No need for a cast.
return n_;
}
从 const
函数中 return 一个 const int*
更有意义。你不想要这样的东西:
const A a;
a.n()[0] = 10;
这颠覆了对象的 const
-ness。您可以使用以下方法来防止这种情况:
const int* n() const
{
// No need for a cast either.
return n_;
}
不,这不是 const_cast
的有效用法。
您的函数不是在修改数组,而是将修改数组的权限授予调用者。因此,它本身应该拥有这些权利。您不能授予某人访问您自己无权访问的内容的权限。所以这个方法不应该是const,const转换就没有必要了。
您可能还需要函数的 const 版本,returns 和 const int*
。这与 std::vector::operator[]
等的原理相同。即使运算符不修改向量,它也授予修改向量的权限,因此它不是 const 函数。 (但还有一个 const 重载版本,returns 一个 const 引用,因此不授予修改 vector 的权利)
一般来说,用 const_cast<>
将 T const
转换为 T
几乎总是不必要的。这是因为常量对象正在转换为非常量临时对象,无需强制转换即可安全地完成此操作。
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
实际上是可修改的(如果指针指向实际的只读内存,则可能不是),或者如果您知道 [=20] 的用户=]实际上不会尝试修改n
.
对于您的示例,您似乎认为您的 const
方法应该 return 指向对象所持有数据的指针,以便调用者可以修改数据。也就是说,由于 n()
方法被声明为 const
,这意味着被访问的对象的内容应该被认为是常量。因此,n_
是常量 int
的数组,它将衰减为指向常量 int
的指针,但您希望 return 指向 int
的指针。
如果您希望 n_
可修改,无论对象是否被视为常量,您可以使用 mutable
声明该意图。这将使 n_
被视为非常量,即使包含对象是 const
,因此 const_cast
变得不必要。
class A
{
private:
mutable int n_[10];
public:
/* ... */
int* n() const
{
return n_;
}
};