【问题标题】:Given the declaration, `std::unique<T> p;`,why `!p` is legail since there is no memory function 'operator !()' for `std::unique<T>`鉴于声明,`std::unique<T> p;`,为什么`!p`是合法的,因为`std::unique<T>`没有记忆函数'operator !()'
【发布时间】:2020-05-26 05:40:33
【问题描述】:

正如下面的代码,我不明白为什么!p 是合法的,因为std::unique&lt;T&gt; 没有成员函数'operator !()'。

由于std::cout &lt;&lt; p.get() &lt;&lt; std::endl; 是合法的,我认为p 是一个对象,而不是一个指针。所以我很困惑。

有人可以帮我一个忙吗?

std::cout << "unique ownership semantics demo\n";
  {
      auto p = std::make_unique<D>(); 
      std::cout << p.get() << std::endl;  //I think p is an object, not an pointer.
      auto q = pass_through(std::move(p)); 
      assert(!p);  //Why it is legial?
      q->bar();   
  } 

【问题讨论】:

    标签: c++ unique-ptr


    【解决方案1】:

    !p 被编译时,编译器会隐式调用unique_ptr&lt;T&gt; 拥有的operator bool,然后将其取反。

    更多详情请见here

    【讨论】:

    • 如果我理解正确的话,如果我自己创建的相关类具有相应的成员函数,!my_object_name 将调用operator bool。我说的对吗?
    • @sunshilong369 是的,你是对的。通常将此类运算符设为explicit 以防止不必要的转换。但即使在我给出的链接中描述的上下文中明确执行转换。
    • 很高兴再次见到。感谢您的澄清。
    • 又提出一个问题,为什么std::unique_prt&lt;T&gt; 不直接重载! 运算符?
    • @sunshilong369 我不知道这不起作用的任何原因,但由于隐式转换规则是为希望隐式转换为 bool 的类设计的,因此没有必要。虽然在 C++11 之前,像这样的类会重载 operator !
    【解决方案2】:

    !p 是合法的,因为有一个明确定义的函数可以将 unique_ptr 转换为 bool

    https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool

    explicit operator bool() const noexcept;
    

    !p 被翻译为!(p.operator bool())

    【讨论】:

      【解决方案3】:

      回答您的其他问题:

      std::cout &lt;&lt; p.get() &lt;&lt; std::endl; 之所以有效是因为

      • get() 返回 unique_ptr 持有的指针
      • operator&lt;&lt; 具有接受 void* 指针作为输入的重载
      • 任何指针都可以隐式转换为void*

      p 确实是一个对象,而不是一个指针。但是get() 返回一个指针。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-10
        • 2020-11-03
        • 2021-01-02
        • 1970-01-01
        • 1970-01-01
        • 2023-02-16
        相关资源
        最近更新 更多