【问题标题】:typedef with const and without const qualifier带 const 且不带 const 限定符的 typedef
【发布时间】:2015-08-26 10:59:07
【问题描述】:
    typedef void* TVPtr;
    typedef const void* CTVPtr;

const TVPtr func3 (const TVPtr p)
{
    return p;
}

const void* func4 (const void* p)
{
    return p;
}

CTVPtr func5 (CTVPtr p)
{
    return p;
}


int main ()
{
    const uint64_t i = 10;

    func3(&i);  // compilation error here
                // cannot convert argument 1 from 'const uint64_t *' 
                // to 'const TVPtr' Conversion loses qualifiers    
    func4(&i);  // no compilation error
    func5(&i);  // no compilation error
    return 0;

}

我不明白为什么有错误是一种情况而不是其他两种情况?

【问题讨论】:

  • 这将是您永远不应将指针隐藏在 typedef 后面的众多原因之一。

标签: c++ c typedef


【解决方案1】:

const TVPtr 不是const void*,而是void* const。换句话说,它不是指向const void 的指针,而是指向voidconst 指针。由于i 被声明为const,它会很高兴地绑定到const void*,而不是void* const,因为这会丢弃对象本身的const

【讨论】:

  • 为什么要把 const TVPtr 当作 void * const?为此,我会写 TVPtr const。
  • TVPtr 是一个指针,因此添加 const 使其成为 const 指针。它不会将constness 注入到类型中。
【解决方案2】:
const TVPtr

意思是:

void * const  //correct

不是这个:

const void*   //wrong

你似乎认为。


可视化可以影响你的理解。

这就是为什么我认为在类型后面加上const 是一种更好的做法的原因之一。所以如果你有这种做法:

void const * x;

而不是

const void * x; //same as void const *x!

那么它有助于 typedef 和模板。

例如,取这个typedef:

typedef void* voidptr;

现在,如果您编写以下内容并尝试想象它是什么:

voidptr const x;

那么您更有可能将其可视化为:

void* const x; //correct

事实上就是这样。

在类型之前加上const 是反直觉的:

const voidptr x;

好像是:

const void* x; //wrong

这实际上是错误的——它仍然是这样的:

 void* const x; //correct

所以在类型后面加上const 有助于可视化最终类型。

【讨论】:

  • 我认为返回类型没有问题,但输入参数。其次,为什么它对另外两个 func 调用 func4、func5 有效?我的情况是指针指向的东西是常量,而不是指针是常量。
  • 使用const void*。没有办法可以使用 typedef 并表示它 const void*。不过,您可以为 const void* 定义另一个 typedef。
  • 你可以说像const typename std::remove_pointer<TVPtr>::type* 这样可怕的东西,但为什么不直接说const void*
  • @Nawaz 您刚刚详细解释了为什么 void const * 是一个好主意,然后在 cmets 中您建议 const void * >。>
  • @MattMcNabb:很好的收获。在我看到 Abhishek 使用 const void* 和其他有这种做法的人之后,我实际上是在墨守成规。有时,我会通过准确说出他们想要的内容来节省时间,尤其是当我已经说得够多的时候。
【解决方案3】:

func3 需要一个非 const 类型,并承诺不会通过参数列表中类型前面的 const 关键字来更改它。由于 CTVPtr 是指向 const 数据的指针,因此其他人可以使用指向 const 类型的指针。

我认为混淆来自您使用的 const 关键字,这实际上意味着 func3 不会更改 p 指向的数据,而不是说 func3 将接受 const TVPtr。

如果你真的想将 i 的地址传递给 func3,你可以这样转换它

func3( (void*)&i);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-10
    • 1970-01-01
    • 2015-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多