微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么这不会创建悬空引用?

如何解决为什么这不会创建悬空引用?

C26830: Assigning by value when a const-reference would suffice

我认为 VS2019 建议会创建一个悬空的参考情况,但我对其进行了测试,它似乎有效。这里发生了什么?


    template<typename MessageType>
    class Queue {
      inline static std::vector<MessageType> messages;
    public:
      static bool isEmpty() {
        return messages.size() == 0;
      }

      template <typename... Args>
      static void emplace(Args&&... args) {
        messages.emplace_back(std::forward<Args>(args)...);
      }

      static MessageType pop() {
        auto const& val = messages.back();
        messages.pop_back();
        return val;
      }
    };

看起来最后一条消息存活的时间足够长,可以复制到返回值中。这是好的做法吗?

解决方法

看起来最后一条消息存活的时间足够长,可以复制到返回值中。这是好的做法吗?

不幸的是,没有,也没有。 std::vector<T>::back 的返回类型是左值引用。也许智能感知认为它是一个右值引用,在这种情况下,由于规则here,它的生命周期会被延长。

但事实并非如此,这里的用法是未定义的行为。这是因为引用所指的列表中的项目已被销毁。它可能仍然有效的原因是因为该项目的内存仍然存在,因此可以正确读取。这只是运气(或不幸,如果您希望能够找到这些错误)。如果被 pop_back 销毁的项目保留了其他内存,那么您可能会看到不同的结果,例如 SEGFAULT。

,

我认为这个建议是正确的,而且是正确的,但前提是你以非常人为的方式解释它。

首先,它告诉您的唯一一件事是 .back() 返回一个引用并且它不需要需要被分配。 当然,该引用可能会在以后悬空,实际上它很大程度上取决于 std::vector 的具体实现。 你不想那样。

回答您的问题,是的,行 .pop_back() 有时会创建悬空引用,具体取决于实现和运行时条件。形式上,换句话说,UB。

(来自https://en.cppreference.com/w/cpp/container/vector/pop_back

迭代器和对 last 元素的引用以及 end() 迭代器都无效。

其次,您无论如何都会返回一个副本,所以“某物”是可疑的,这与 IDE 的建议一致。 您不需要副本(IDE 也是如此),但也不需要参考。 您可能想要的是移动副本,很可能。

如果 Message 可以移动并且应该大致正确并且 IDE 不应建议任何改进,则这是有效的。 最坏的情况是复制,这是正确的行为。

      static MessageType pop() {
        auto val = std::move(messages.back());
        messages.pop_back();
        return val;
      }

总而言之,除此之外的任何 UB 或讨论都是您想要的最概念化的表达。


注意:我认为 auto valauto const val 更好,因为您允许 NRVO。我不是 100% 确定。


版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。