鉴于声明,`std::unique<T> p;`,为啥`!p`是合法的,因为`std::unique<T>`没有记忆函数'operator !()'
Posted
技术标签:
【中文标题】鉴于声明,`std::unique<T> p;`,为啥`!p`是合法的,因为`std::unique<T>`没有记忆函数\'operator !()\'【英文标题】: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<T>
没有成员函数'operator !()'。
由于std::cout << p.get() << 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();
【问题讨论】:
【参考方案1】:当!p
被编译时,编译器会隐式调用unique_ptr<T>
拥有的operator bool
,然后将其取反。
更多详情请见here。
【讨论】:
如果我理解正确的话,如果我自己创建的相关类具有相应的成员函数,!my_object_name
将调用operator bool
。我说的对吗?
@sunshilong369 是的,你是对的。通常将此类运算符设为explicit
以防止不必要的转换。但即使在我给出的链接中描述的上下文中明确执行转换。
很高兴再次见到。感谢您的澄清。
又提出一个问题,为什么std::unique_prt<T>
不直接重载!
运算符?
@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 << p.get() << std::endl;
之所以有效是因为
get()
返回 unique_ptr
持有的指针
operator<<
具有接受 void*
指针作为输入的重载
任何指针都可以隐式转换为void*
。
p
确实是一个对象,而不是一个指针。但是get()
返回一个指针。
【讨论】:
以上是关于鉴于声明,`std::unique<T> p;`,为啥`!p`是合法的,因为`std::unique<T>`没有记忆函数'operator !()'的主要内容,如果未能解决你的问题,请参考以下文章
调整 std::vector<std::unique_ptr<T>> 大小的性能
来自 T* 的 std::unique_ptr<T> 的构造函数显式背后的原因是啥?
boost::ptr_vector 与 std::vector<std::unique_ptr<T>>? [关闭]