4

众所周知,应该避免使用 const_cast 来删除指针的 const-ness。

但反过来又如何呢?

对于我的用例,我有一个从非常量源缓冲区复制数据(字节)的函数。我认为一个好的设计决策是根据该源缓冲区完全 const 声明参数。

void copyfunction(const char* const data) { ... }

对于像下面这样的函数调用,这将导致指针类型错误“const char* const <-> char*”。

void main() {
    char sourcebuffer[] = {0x00};

    copyfunction(sourcebuffer);
}

当然,现在我可以简单地将其声明sourcebuffer为 const,但在我的情况下,我无法访问该变量,因为它来自不同的代码位置(外部库)。

void main() {
    char sourcebuffer[] = {0x00};

    copyfunction(const_cast<const char* const>(sourcebuffer));
}

然而,超出的代码可以工作,但它是好的风格(根据我的用例)吗?

我认为声明copyfunctionas const 的参数可以确保用户不会修改(只读)指针或源缓冲区本身的位置。因此,在这种情况下, const_cast 只是启用函数调用而不是故意删除指针的 const-ness 所必需的邪恶......

问候

4

2 回答 2

6

您不应该使用const_cast添加const,因为:

  1. 这是不必要的。T*隐式转换为const T*. 您的问题表明这char sourcebuffer[] = {0x00}; copyfunction(sourcebuffer);是一个错误,但事实并非如此。

  2. 它可能(尽管不太可能)有害。它可以volatile从指针类型中删除,这不是这里的意图,如果sourcebuffer声明为volatile sourcebuffer[].

于 2014-01-06T18:58:58.273 回答
5

您不应该使用const_cast添加const,因为

  1. 在操作安全的情况下,几乎总是不需要。 隐含地int*变成了。const int*

  2. 它可以做一些你不希望它做的事情。它可以剥离,或者让您错过在变量中其他位置添加volatile的事实,而您现在默默地剥离它们。constconst_cast

  3. 在需要添加的情况下const,它的使用是危险的,难以推理。

在某些情况下,您需要调用const_cast以添加const不会隐式发生的情况。

void assign_ptr( int const*& lhs, int const* rhs ) { lhs = rhs; }
int const foo = 7;
int* bar = nullptr;
assign_ptr( const_cast<int const*&>(bar), &foo );
*bar = 2; // undefined behavior!
std::cout << foo << "@" << &foo << "\n"; // will print probably 7@something
std::cout << *bar << "@" << bar << "\n"; // will print probably 2@same address as above!

上面的调用assign_ptr只添加了const,但它不会隐式发生。

它的副作用是修改 of*bar是未定义的行为,因为它修改了声明的变量const(它使bar, a int*, 指向fooa const int)。

因此,虽然const_cast需要assign_ptr编译调用,但这是因为它是 unsafeconst_cast不会使它更安全,它只是隐藏错误。

这是矩形-正方形问题的一个特例。Squares 不是 Rectangles,因为如果你改变 Square 的宽度,它的高度也会改变,而这在你修改 Rectangle 时不会发生。同样,int**不是int const**。(请注意,不可变的 Squares 是一种不可变的 Rectangle;它是导致问题的突变。在指针的情况下, aint*const*是 a int const*const*:“更高级别”指针的可变性会导致问题。)

于 2014-01-06T19:25:05.500 回答