const void*比void*提供了什么值

What value does const void * offer over void *?

本文关键字:void 什么 const      更新时间:2023-10-16

在C++中,使用const void *作为函数在void *上的参数类型有什么值吗?由于void *是不透明的,除了用户使用reinterpret_cast之外,还有修改的风险吗?在这种情况下,他们也可以在const void *上使用const_cast,因此人们真的买了什么吗?我之所以这么问,是因为我使用了一个用于共享指针的实用工具模板类,该类在void上提供了专门化以避免void &问题,但没有为const void提供专门化,因此我想知道这是一个疏忽,还是永远不需要?

它提供了const在其他指针类型上提供的相同好处:除非显式丢弃const-ness,否则无法修改所指向的内容。在接口中,const void*是客户端代码的一个符号,您传入的任何代码都可以读取,但不能写入。例如,std::memcpy被声明为

void *memcpy(void *dest, const void *src, std::size_t count);

其用信号表示它将读取CCD_ 14并写入CCD_。当然,如果它真的是在C++中实现的(可能但不太可能),它必须将两个指针都强制转换为其他类型。

如果你觉得这"没有给你买任何东西",那么const关键字本身显然没有价值。

memcpy采用两个指针参数,一个是void*,另一个是const void*。第二个参数可以从const char*(或其他指向常量对象类型的指针)参数隐式转换,而第一个参数则不能。

隐式转换的缺失就是这个值——它迫使用户在他们想要的(不太可能的)事件中故意丢弃const,而不是意外地丢弃它

然后,在memcpy或类似函数的实现中,程序员在尝试修改其引用之前,必须先const_cast或C风格的const void*参数。他们将能够static_cast的非常参数和修改其引用。你需要写的演员阵容希望能告诉你所做的是否明智。

我认为,如果您的shared_ptr助手函数需要专门处理void,那么它们将需要专门处理所有符合cv的void。这是四种情况:voidconst voidvolatile voidconst volatile void。但是,如果这些功能的用户过去曾在shared_ptr<void>上尝试过,并抱怨它不起作用,但从未在shared_ptr<const void>上尝试过它,那么问题可能就没有出现。

也许shared_ptr<void>已经很不寻常了,它还没有出现。也许使用shared_ptr<void>的人倾向于不介意丢弃cv限定符,因为每当有人最终恢复正确的类型时,他们也会恢复正确的限定符。

仔细想想,shared_ptr<const void>到底起作用了吗?还是shared_ptr中调用deleter的代码需要从T*void*的隐式转换?我不记得我是否用过shared_ptr<const T>

不要忘记const的"文档值"。即使有人总是可以把它扔掉,const也可以用来表明被指向的东西不应该通过指针改变的初衷。const_cast(和reinterpret_cast)应始终小心使用,必要时应让程序员暂停使用。

是的,const总是有(一些)相同的优点:它记录了内容不应该突变的事实。

想象一下以下代码:

int const object = some_value();
some_function(&object);

只有当函数参数声明为void const*时,此调用才会编译,否则客户端将需要const_cast来丢弃常量。当然,我们既不希望客户有这种不便,也不希望他们在数据上撒谎(通过消除不确定性)。

"自我文档化"代码仍然有好处。

store_pod(const void* data, std::size_t bytes);

不带任何注释可以让您看到指向的数据不会被修改。

此外,请注意,要打破const的承诺,函数需要同时执行const_castreinterpret_cast

const的所有用途一样,它有两个用途。在函数的实现中,它将帮助编译器检测误用,正如您所提到的,可以通过const_cast(或C样式转换)强制和静音。

const还有第二个目的,它提供了对象不会被修改的承诺,并且在这样做的过程中,用户可以将指针传递到const对象(假设你会遵守承诺),从而有效地允许更广泛地使用你的函数。这可以从这个简单的例子中看出:

void foo( const void* );
void bar( void* );
int main() {
    const int value = 10;
    foo( &value );          // correct, the function promises not to modify the value
    //bar( &value );        // error, this would break const correctness
}