为什么我在将“float **”转换为“const float **”时出现错误?

33
我有一个函数,接受float**作为参数,我试图将其修改为接受const float**
编译器(g++)不喜欢它并发出错误:invalid conversion from ‘float**’ to ‘const float**’
这让我感到非常困惑,因为我知道(并验证过)可以将char*传递给接受const char*的函数,那么const float**为什么不行呢?
4个回答

25

请参阅 为什么将Foo**转换为const Foo**时会出错?

这是因为将 Foo** 转换为 const Foo** 是无效和危险的... Foo** 转换为 const Foo** 的原因是这样会让您在没有强制转换的情况下静默地意外修改 const Foo 对象。

该引用继续给出了一个示例,说明这种隐式转换如何使我能够修改一个 const 对象而不需要进行强制转换。


3
也许添加摘要会更好地补充你的答案。 - GManNickG

23

这是一个非常棘手的限制。它与语言的别名规则有关。看一下标准的规定,因为我以前遇到过这个问题:

(Page 61)

[Note: if a program could assign a pointer of type T** to a pointer of type const T** (that is, if line //1 below was allowed), a program could inadvertently modify a const object (as it is done on line //2). For example,

int main() {
  const char c = 'c';
  char* pc;
  const char** pcc = &pc; //1: not allowed
  *pcc = &c;
  *pc = 'C'; //2: modifies a const object
}

—end note]


14

其他答案详细解释了为什么这是C ++中的错误。

让我回答你问题的背后。您想在函数的接口中声明,您的函数不会修改包含在数组中的浮点值。很好的意图,使您的函数可用于调用const float **数组。您问题的背后是如何在不采用丑陋转换的情况下实现此目的。

实现您想要的正确方式是将函数参数类型更改为const float * const *

星号之间的附加const确保编译器不会尝试在数组中存储指向const float的指针,因为该类型声明指针值也是const。

现在,您可以使用float **(这是您问题中的示例),const float **const float * const *参数调用此函数。


是的。const语法规则是,如果它在类型的左侧,则紧密绑定到其右侧的内容,否则修改其左侧的内容。因此,const intint const是相同的类型,const int*int const*都是指向常量int的指针,int* const是指向无法更改为int的指针,而const int* constint const* const是指向无法更改为无法更改的int的指针。无限扩展。 - Ben
你想要实现的正确方式是将函数参数类型更改为const float * const *。这正是我在寻找的答案,应该更加突出。 - Eric Hein
如果我正在使用签名为 foo(const char** bar) 的 API,但我无法控制该 API,那么在函数调用中如何解决此错误? - Nimrod Morag

9
如果你将参数转换为 const float**,那么你可以在参数所指向的内存位置存储一个 const float*。但是调用函数认为这个内存位置应该包含一个非常量的 float*,并且可能尝试更改这个指向的 float
因此,你不能将 float** 强制转换为 const float**,这会允许你在期望可变值的位置存储常量指针。
有关更多详细信息,请参见C++ FAQ Lite

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接