【问题标题】:Why can't std::as_const(T &&v) move-return its argument?为什么 std::as_const(T &&v) 不能移动返回它的参数?
【发布时间】:2021-04-19 08:04:46
【问题描述】:

阅读Why does as_const forbid rvalue arguments? 我知道我们当然不能将右值引用转换为左值引用。

但为什么不将右值引用移动到一个值并返回它,即?

template<typename T> 
const T as_const(T&& val) { return std::move(val); } 

这应该也适用于 COW 容器,因为返回值是 const 并且来自它的迭代器不会导致它分离。

也许一些上帝会回答这个问题,但我想不出一个给定的场景,而且那里没有容易获得的 COW 容器 AFAIK。

更新:

考虑一下这个 COW 容器(忽略线程问题):

class mything {
   std::shared_ptr<std::vector<int>> _contents;

   auto begin() { if (_contents.use_count() > 1) { detach(); }
                  return _contents->begin(); }
   auto begin() const { return _contents->begin(); }
   void detach() {
       _contents = std::make_shared<decltype(_contents)>(*_contents); 
   }
   ...
};

移动会很快,并且当在 range-for-loop 中使用时,返回的 const T 将选择 begin() 的 const 版本。

还有一些容器将自己标记为已修改,因此它们的更改可以通过网络发送或稍后同步到另一个副本(用于另一个线程),f.ex。在 OpenSG 中。

【问题讨论】:

  • 我的猜测很简单,这不是函数的用途:它的意思是“将这个非常量引用变成一个常量”,而不是“确保我得到 something const 在所有情况下'。
  • const 上的返回值(不是引用)基本上没有意义
  • @Caleth 不适用于写时复制容器,其非 const begin()/end() 函数会创建新副本(也称为分离),因为它们希望内容发生变化。
  • 返回 std::move(val)T 在任何情况下都会复制 val。此外,return std::move(...) 是一种反模式,通常会禁止 NRVO。但是,即使 NRVO 在返回输入参数时也无济于事,总会涉及到复制。
  • 好的,如果我们忽略非类 const T 的问题,您的版本仍然会返回一个新的 T 实例。左值引用重载返回对同一对象的引用会产生误导,而右值一 - 一个新对象。

标签: c++ c++17 rvalue-reference


【解决方案1】:

我将它理解为一个附加功能,但要避免一些措施:获取具有地址的东西的 const 视图。

而且因为临时没有地址,所以也不应该有它的 const 视图。

移动值而不是仅仅添加 const 会改变它的语义(我们已经有了std::move

如果 as_const 到一个临时的会延长它自己的生命周期,那么如果不绑定它会浪费空间,例如:

{
   as_const(f()); // if the lifetime would be extended
...
 } // not bound, but space wasted

例如 as_constconst 添加到 value 而不是 type,因此它可以节省一些输入,例如 static_castadd_const

通常将 const lvalue ref 绑定到临时对象,会延长临时对象的生命周期,例如:

int f() { return 3; }

{
   const auto& x = f();
    ... use x .. ok
}

但是这样的事情会以悬空引用结束:

{
   auto& x = as_const(f()); // one could wrongly think that temporary lifetime is extended, but it's not
    ... x dangles ..
}

【讨论】:

  • 这就是为什么我建议从右值引用而不是左值引用返回一个值,因为我们不能,AFAIK,从函数返回右值引用。
  • @Macke - 我们当然可以。这正是std::move 的工作原理。
  • @StoryTeller-UnslanderMonica 那么我需要的是std::move_to_const 吗? :) .. 实现我的问题?我能做到。 :)
  • 顺便说一句,不是 r-value ref 的全部点,您可以将其移动到某个位置或类似位置。所以将它移动到我们返回的值还不错。它就像从一个变体中移出一些东西并返回它。
  • 我认为 r-value 是一种可以移动的“标志”。但是,如果一个人真的改变了它与否,IMO 是另一回事。
猜你喜欢
  • 2016-11-10
  • 2014-01-13
  • 2016-12-27
  • 2015-04-30
  • 2019-04-26
  • 1970-01-01
  • 1970-01-01
  • 2013-11-19
  • 2022-12-21
相关资源
最近更新 更多