c – 处理没有标记任何const函数的库的最佳方法是什么?

前端之家收集整理的这篇文章主要介绍了c – 处理没有标记任何const函数的库的最佳方法是什么?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图在我的项目中实现一个C库的使用,该库未在其访问函数上使用const修饰符.到目前为止,我一直在我的所有代码中使用const,但是这个新库导致了两个主要问题:

>如果这些参数是由库定义的类型,则作为const引用传递参数的函数不能使用参数的访问函数.
>具有库定义的类型的成员对象的类不能在const函数中使用这些对象的访问函数.

克服这个问题的最佳方法是什么?最简单的解决方案是简单地从我的代码删除所有const的使用,但这样做会非常令人沮丧.

附加信息:在这种情况下,我可以访问源代码,并且可以看到访问函数不会修改任何内容.我省略了这些信息,因为我对更一般的情况感兴趣.对于我的场景,const_cast似乎是要走的路

PS图书馆作家并不邪恶!这是一个粗略和准备好的代码,他善于开源.我可以放弃图书馆并使用其他人注意到的更专业的东西.但是,对于这个时间有限的小项目,该库接口的简单性使其成为最佳选择.

解决方法

判断库中的函数是否实际修改了什么是多么容易?

如果它很容易辨别,而且它们没有,那么你可以const_cast你的const指针/引用非const并调用函数.您可能希望在库类周围添加一个包装器来为您执行此操作,这样做既繁琐冗长又可以从您的类中获取代码.这个包装器可能是一个子类,它添加了一些const访问器,这取决于你使用库类的方式是否允许它工作.

如果很难说,或者他们确实修改了东西,那么你需要在代码中使用非const实例和对库类的引用. mutable可以帮助类型(2),但对于类型(1)的那些你只需要传递非const参数.

有关它可能很难的原因的一个例子,请考虑库作者可能写了这样的东西:

struct Foo {
    size_t times_accessed;
    int value;
    int get() {
        ++times_accessed;
        return value;
    }
};

现在,如果你const_cast一个Foo的const实例并调用get(),你有未定义的行为[*].因此,您必须确保实际上不会修改它所调用的对象.你可以通过确保永远不会创建任何Foo的const实例来缓解这一点,即使你确实对非const实例进行了const引用.这样,当你const_cast和调用时,至少不会导致UB.它可能会使您的代码混乱,字段会不断更改您的函数声称不会修改的对象.

[*]为什么它是未定义的行为?它必须是,语言可以保证const对象的值永远不会在有效程序中更改.这种保证允许编译器做有用的事情.例如,它可以将静态const对象放在只读数据部分中,并且可以使用已知值优化代码.它还意味着具有可见初始化程序的const整数对象是编译时常量,标准使用它来将其用作数组大小或模板参数.如果修改const对象不是UB,那么const对象将不会是常量,并且这些事情是不可能的:

#include <iostream>

struct Foo {
    int a;
    Foo(int a) : a(a) {}
};

void nobody_knows_what_this_does1(const int *p); // defined in another TU
void nobody_knows_what_this_does2(const int *p); // defined in another TU

int main() {
    const Foo f(1);
    Foo g(1);
    nobody_knows_what_this_does1(&f.a);
    nobody_knows_what_this_does2(&g.a);
    int x;
    if (std::cin >> x) {
        std::cout << (x / f.a); // Optimization opportunity!
        std::cout << (x / g.a); // Cannot optimize!
    }
}

因为f是一个const对象,因此f.a是一个const对象,优化器知道f.a在函数末尾使用时值为1.如果它选择的话,它可以优化分裂.它对g.a不知道同样的事情:g不是const对象,指向它的指针已被传递给未知代码,因此它的值可能已经改变.因此,如果您是nobody_knows_what_this_does1或nobody_knows_what_this_does2的作者,并且您正在考虑const_casting p并使用它来修改其referand,那么只有在您以某种方式知道referand是非const时才能执行此操作.通常你不这样做,所以通常你不使用const_cast.

猜你在找的C&C++相关文章