- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
以下代码:
#include <tuple>
int main ()
{
auto f = [] () -> decltype (auto)
{
return std::get<0> (std::make_tuple (0));
};
return f ();
}
(静默地)生成具有未定义行为的代码 - make_tuple
返回的临时右值通过 std::get<> 和 decltype(auto) 传播到返回类型。所以它最终会返回对超出范围的临时对象的引用。在这里查看 https://godbolt.org/g/X1UhSw .
现在,您可能会争辩说我对 decltype(auto)
的使用是错的。但是在我的通用代码中(元组的类型可能是 std::tuple<Foo &>
)我不想总是制作拷贝。我真的很想从元组中提取确切的值或引用。
我的感觉是 std::get
的重载很危险:
template< std::size_t I, class... Types >
constexpr std::tuple_element_t<I, tuple<Types...> >&&
get( tuple<Types...>&& t ) noexcept;
虽然将左值引用传播到元组元素上可能是明智的,但我认为这不适用于右值引用。
我相信标准委员会非常仔细地考虑过这个问题,但是谁能向我解释为什么这被认为是最佳选择吗?
最佳答案
考虑以下示例:
void consume(foo&&);
template <typename Tuple>
void consume_tuple_first(Tuple&& t)
{
consume(std::get<0>(std::forward<Tuple>(t)));
}
int main()
{
consume_tuple_first(std::tuple{foo{}});
}
在这种情况下,我们知道 std::tuple{foo{}}
是临时的,它将在 consume_tuple_first(std::tuple{foo{}})
的整个持续时间内存在表达。
我们希望避免任何不必要的复制和移动,但仍传播 foo{}
的临时性至 consume
.
唯一的方法是使用 std::get
使用临时 std::tuple
调用时返回一个右值引用实例。
改变 std::get<0>(std::forward<Tuple>(t))
至 std::get<0>(t)
产生编译错误(如预期的那样)(on wandbox)。
有一个 get
按值返回的替代方案会导致额外的不必要的移动:
template <typename Tuple>
auto myget(Tuple&& t)
{
return std::get<0>(std::forward<Tuple>(t));
}
template <typename Tuple>
void consume_tuple_first(Tuple&& t)
{
consume(myget(std::forward<Tuple>(t)));
}
but can anyone explain to me why this was considered the best option?
因为它启用了可选的通用代码,可以在访问元组时无缝传播临时右值引用。按值返回的替代方法可能会导致不必要的移动操作。
关于c++ - std::get 在右值引用元组上的行为是否危险?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47905333/
编辑:澄清一下,我明白为什么这段代码不起作用,我并不是要修复它,而是想了解如果这段代码可以在没有语义错误的情况下编译会有什么危险。 我发现下面的代码会导致静态语义错误。我知道这是因为 std::lis
我想知道 C# 枚举以及重复值会发生什么。我创建了以下小程序来测试: namespace ConsoleTest { enum TestEnum { FirstElem
正如我在另一个 SO 问题中指出的那样,我遇到了 this article .当我通过 MSVC7.1 编译 boost 1.40 时出现了这个问题,并且弹出了几个 C4251 警告。 现在,在阅读上
我有以下弹出窗口代码(客户端请求)。它使用 eval ,我知道这是危险的。有没有办法重写下面的脚本,使其不使用 (eval)? /* exported popup_default , popup_he
NTFS 文件可以有对象 ID。可以使用 FSCTL_SET_OBJECT_ID 设置这些 ID .然而,msdn article说: Modifying an object identifier c
我一直在学习命令行参数解析。关于这个已经有很长的线索了,我不想在这里挑起一个: Using getopts in bash shell script to get long and short com
这个问题在这里已经有了答案: How to configure ContextMenu buttons for delete and disabled in SwiftUI? (4 个回答) 4 个月
为什么在 linux 的中断处理程序中禁止 printk 或 (I/O)。?在什么情况下中断处理程序中的 I/O 会导致 linux 系统中的死锁? 最佳答案 关于 printk(),它是侵入性的。例
不是 Invoking virtual function and pure-virtual function from a constructor 的重复项: 以前的问题与 C++ 03 相关,而不是
我正在使用 lateinit 属性以避免使用 ?运算符(operator)。我有很多 View 属性是第一次在 getViews() 函数中分配的。如果该功能不存在,我的应用程序将与来自 Kotlin
我最近在使用 fputs 时遇到了问题:当使用 fputs 在文本文件中打印一些字符串时,我碰巧得到了除 A-Z、a-z、0-9 之外的其他字符(不属于字符串的字符) .我绝对确保所有字符串都以空字符
在仅包含字节数组的结构上使用 #pragma pack(1) 是否危险/有风险?例如。这个: #pragma pack(1) struct RpcMessage { uint8_t proto
我是一名优秀的程序员,十分优秀!