【问题标题】:What to do when library function parameters aren't const当库函数参数不是 const 时该怎么办
【发布时间】:2019-01-08 21:09:40
【问题描述】:

我的大部分代码库都是不可变的;但是,由于语言设计的怪癖,我无法标记我的变量const

在绝大多数情况下,尤其是在与 C 代码互操作时,我发现函数参数没有标记为 const,即使它们可证明不会修改它们。 一个这样的例子是fts_open(...)。此时,编译器迫使我从大部分代码中繁琐地删除 const 限定符,从而消除了它提供的安全性。

一个简单的解决方案是使用-fpermissive 进行编译,但这完全违背了我的意图。

除了重写曾经编写的每一个 C 库之外,我还能做些什么来从依赖编译器中获得好处?

即这种类型的代码不起作用:

void function(immutable_type const &param)
{
    char const * const fts_arg[2]{std::data(param.path), nullptr};
    FTS *tree = fts_open(fts_arg, FTS_OPTIONS, nullptr);
    ...
}

此时我必须:

  • fts_args 变量中删除 const。
  • 从函数参数中删除 const。
  • 从数据类型定义中的 path 中删除 const。
  • 从传递给function的变量中删除const。
  • 从整个调用链中递归删除consts。

谢谢。 :)

【问题讨论】:

  • 你知道调用是否真的是 const 吗?
  • 如果您确实确定库不会修改数据,您可以编辑包含的标题,以便它们具有必要的const — 或制作您自己的 C++ 友好版本的标题。
  • 总是可以通过副本。效率低下,但它会工作。
  • 显然,您链接中讨论的问题使得唯一可行的解​​决方案是 const_cast将参数设置为 fts_open 预期的类型(或从您的类型中删除有问题的 const)。由于语言(C 和 C++)存在问题,上游声明不太可能更改。
  • 不是const_cast本身会导致UB,而是尝试修改const对象,fts_open可能会避免。

标签: c++ constants


【解决方案1】:

这正是const_cast 的用途。如果您绝对知道一个函数不会更改指向/引用的对象,那么尽管引用了一个 const 对象,但可以将指针/引用的常量 const_cast 移开以便将其传递给该函数。

不是 const_casting 来自 const undefined 行为吗?

没有。 const_cast 本身绝不是 UB。但是修改一个 const 对象是。因此,如果您无法证明采用非常量指针/引用的函数不会修改对象,那么将 const_casted 引用传递给该函数是不安全的。

还要考虑将来是否可能更改实现以使用非常量。


如果您无法证明非 constly 引用/指向的对象不会被修改,您可以制作包装函数的 constly 引用参数的本地副本。此副本的开销可能很小 (int) 或非平凡 (long std::vector)。

如果你不能证明对象不会被修改,并且复制代价高昂(或不可能),那么作为最后的手段,你必须摆脱你自己的论点的常量性(并将更改传播到调用链)。或者在实现中使用其他 API。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-23
    • 1970-01-01
    • 1970-01-01
    • 2015-10-12
    • 2019-04-02
    • 2023-03-20
    • 2017-11-20
    相关资源
    最近更新 更多