【问题标题】:c++ why is it valid to dereference a shared_ptr to a const type to a non-const variable?c ++为什么将shared_ptr取消引用到const类型到非常量变量是有效的?
【发布时间】:2020-11-17 21:47:24
【问题描述】:

为什么以下是合法的?

std::shared_ptr<const Foo> foo = std::make_shared(new Foo());
Foo bar = *foo;

取消对const Foo的引用不应该是合法的吗?

【问题讨论】:

    标签: const-correctness


    【解决方案1】:

    因为你已经调用了复制构造函数,并且新创建的变量不会影响原始变量。这是一样的

    const int x = 3
    int y = x;
    

    x被复制到y,这样就没有问题了。然而,这是非法的:

    Foo *bar = foo;
    

    或者这个

    Foo &bar = *foo;
    

    当然,编译器只是以“浅”的方式检查这个,所以你绝对可以自己 FooBar。要求编译器做得更好是太难了。一个内存泄漏的例子(泄漏不是重点,我只是懒惰):

    #include<memory>
    #include<iostream>
    
    struct Foo {
         int *x;
         Foo(int x) : x(new int(x)) {}
     };
    
    int main() {
        std::shared_ptr<const Foo> foo = std::make_shared<Foo>(3);
        Foo bar = *foo;
        *bar.x = 5;
        std::cout<<*foo->x<<"\n";
        return 0;
    }
    

    输出是 5... 这种类型的错误很糟糕,并且使诸如 3 规则(5 等)和 const 正确性(在您的所有代码中)之类的东西很重要。事实上,你甚至不必那么努力。这也“打破”了:

    #include<memory>
    #include<iostream>
    
    struct Foo {
         int *x;
         Foo(int x) : x(new int(x)) {}
     };
    
    int main() {
        std::shared_ptr<const Foo> foo = std::make_shared<Foo>(3);
        *foo.x = 5;
        std::cout<<*foo->x<<"\n";
        return 0;
    }
    

    这种行为对于 C++ 来说并不特殊。在我的脑海中,Python 中包含列表的元组是另一个通常被认为是 const 但可以更改的示例。

    我猜你可以称之为“浅常量”,因此,这是预期的行为,而不是真正的错误,尽管通常是它们的原因 - const 保证对象,而不是其中包含的任何内容(如果它是一个容器,则包含比对象的字段更“内部”的层次上的含义)。一些容器可能会提供额外的保证,但必须实施。

    【讨论】:

    • 但是 const Foo 也意味着我不能在上面调用非常量函数,而我可以在赋值后调用非常量函数
    • @user1282931 我不明白你的意思。在您的示例中,bar 是原始 foo 的全新副本。它调用什么方法有什么关系?
    • @user1282931 除非你有一个错误的复制构造函数和动态内存分配?这可能是个问题,编译器不会发现。
    • 如果 Foo 存储指向其他对象的内部指针怎么办?它们将被共享,而 const 函数不能更改这些内部对象(通过在它们上调用非 const 函数),非 const 函数可以并且将会更改底层的内部对象。我知道我可能错了,但这就是我的困惑所在
    • @user1282931 检查更新的答案。编译器无法处理非浅层 const 检查。简而言之,如果你不安全地编码,你就完蛋了。
    猜你喜欢
    • 2018-07-16
    • 1970-01-01
    • 2020-11-19
    • 1970-01-01
    • 2010-12-27
    • 1970-01-01
    • 1970-01-01
    • 2020-03-19
    • 2020-10-27
    相关资源
    最近更新 更多