【问题标题】:Const correctness of operator* in std::unique_ptrstd::unique_ptr 中 operator* 的 const 正确性
【发布时间】:2022-08-04 05:15:07
【问题描述】:

为什么 std::unique_ptr 的 \'operator*\' 成员函数可以标记为 const (https://en.cppreference.com/w/cpp/memory/unique_ptr/operator*) 而函数如 \'front()\'、\'back()\'、\'operator[]\' std::vector 中的 etc 不被标记为 const?两者都返回对他们管理的资源的非常量引用。

核心问题是我无法理解第一部分,即为什么我们能够将 \'operator*\' 标记为 const,即当 \'*this\' 时返回类型如何是 \'T&\'该函数中的指针将是一个 const 指针(由于该函数被标记为 const)?

  • std::vector 具有 beginfrontoperator[] 的 const 版本
  • std::unique_ptr::operator* 不会改变唯一指针的内部状态 - 所以它应该被标记为 const
  • 因为operator* 不能改变指针。 const unique_ptr<char> ptrchar* const ptr 变量具有相同的语义 - 您可以更改指向的内容,但不能将指针重定向到其他地方。
  • *this 不是指针,它是 const unique_ptr<T>,这并不意味着 T 是 const。也就是说,const unique_ptr<T> 不是“喜欢”const T*,而是“喜欢”T* const。 (这有助于根本不将智能“指针”视为指针,因为它们不是。它们只是常规类。)
  • 这似乎是对有关\"const pointer\" vs \"pointer to const\" 的许多问题的新看法。

标签: c++ unique-ptr const-correctness


【解决方案1】:

区别在于a的定义容器.

std::vector 被考虑一个容器.这意味着由std::vector 管理的对象被考虑向量的一部分.

如果向量为const,则从front()back()operator[] 返回的引用必须为const。修改这些对象将修改向量。

但是,std::unique_ptr不是容器.它管理的对象不被视为std::unique_ptr 的一部分。这意味着修改托管对象不被视为修改指针。

因此,在指针类型上使用operator* 永远不会改变指针本身,因此始终可以将操作视为const


std::optional 可能会为这种差异提供一些有用的背景信息。

尽管语法类似于指针,但它实际上是一个容器(max_size 为 1)。因为它包含它的托管对象its operator* must obey the same const rules that a container does.

【讨论】:

  • 我认为std::unique_ptr一个容器,它包含的是一个指针。但是,std::unique_ptr 不包含指向的对象,const 仅绑定到容器。
  • @Drew Dormann - 这是否意味着 unique_ptr 和 vector 之间某些函数的常量性差异仅仅是由于语义与 C++ 中的容器类相关联?
  • @not_that_guy123 是的。 std::vector 模拟数组的属性,而std::unique_ptr 模拟指针的属性。说“这个数组不会改变”不具有相同的含义“这个指针不会改变”,即使指针指向数组。
  • 这很有意义。谢谢!
【解决方案2】:

上面 Drew Dormann 的出色回答解决了我的核心困惑。在此处添加摘要(因为作为评论发布太长)以完全清楚。

疑点一: 即使std::unique_ptr::operator*() 被标记为 const 函数,我们如何才能使用T& 作为返回类型?

答案 1std::unique_ptr 只存储指向正在管理的数据的指针(数据本身不存储在类中,而是存储在堆上)。我们能够将其operator*() 函数标记为 const,因为我们正在返回对正在存储的实际数据的非常量引用,并且由于该数据本身并未存储在类中,因此“const”限定符只是使指向数据的指针const (即我们有一个 const 指针)但是这个 const 指针指向的数据仍然是非常量的,我们可以将非常量引用绑定到它。

疑点二std::vector 也是如此(即,由它管理的数据不存储在类中,而是存储在堆上)但是为什么我们不类似地将 std::vector::front()std::vector::back() 等函数标记为常量?

答案 2:这是由于与 C++ 中的容器类相关的语义。从上面引用德鲁 -std::vector 对数组的属性进行建模,而 std::unique_ptr 对指针的属性进行建模.所以我们的行为就好像std::vector 管理的数据驻留在类中一样。请注意,std::optionalstd::unique_ptr / std::vector 不同,因为被管理的数据实际上存储在类中。

【讨论】:

    猜你喜欢
    • 2018-03-06
    • 2020-03-29
    • 2022-01-10
    • 1970-01-01
    • 2011-05-06
    • 2016-08-03
    • 1970-01-01
    • 1970-01-01
    • 2015-12-16
    相关资源
    最近更新 更多