c++ - 具有 std::minmax 和右值的结构化绑定(bind)

标签 c++ c++17 rvalue structured-bindings

在将 std::minmax 与结构化绑定(bind)一起使用时,我遇到了一个相当微妙的错误。似乎传递的右值并不总是像预期的那样被复制。最初我在自定义容器上使用 T operator[]() const,但它似乎与文字整数相同。

#include <algorithm>
#include <cstdio>
#include <tuple>

int main()
{
    auto [amin, amax] = std::minmax(3, 6);
    printf("%d,%d\n", amin, amax); // undefined,undefined

    int bmin, bmax;
    std::tie(bmin, bmax) = std::minmax(3, 6);
    printf("%d,%d\n", bmin, bmax); // 3,6
}

使用带有 -O1 -Wuninitialized 的 GCC 8.1.1 将导致 0,0 被打印为第一行并且:

warning: ‘<anonymous>’ is used uninitialized in this function [-Wuninitialized]

-O2 的 Clang 6.0.1 也会给出错误的第一个结果而没有警告。

-O0 处,GCC 给出了正确的结果并且没有警告。对于 clang,结果在 -O1-O0 处似乎是正确的。

第一行和第二行不应该是等价的,因为右值仍然可以被复制吗?

另外,为什么这取决于优化级别?特别令我惊讶的是 GCC 没有发出警告。

最佳答案

auto [amin, amax] 中的重要注意事项是auto , auto&等等被应用到组成的对象 e用返回值 std::minmax 初始化,这是一对。本质上是这样的:

auto e = std::minmax(3, 6);

auto&& amin = std::get<0>(e);
auto&& amax = std::get<1>(e);

amin 的实际类型和 amax是指任何 std::get<0> 的引用和 std::get<1>返回该对对象。他们自己返回对早已不复存在的对象的引用!

当您使用 std::tie 时,您正在对现有对象进行分配(通过引用传递)。右值不需要比它们产生的赋值表达式的生命周期更长。


作为一种解决方法,您可以使用类似这样的功能(不是生产质量):

template<typename T1, typename T2>
auto as_value(std::pair<T1, T2> in) {
    using U1 = std::decay_t<T1>;
    using U2 = std::decay_t<T2>;
    return std::pair<U1, U2>(in);
}

它确保对包含值类型。像这样使用时:

auto [amin, amax] = as_value(std::minmax(3, 6));

我们现在得到一个拷贝,结构化绑定(bind)引用这些拷贝。

关于c++ - 具有 std::minmax 和右值的结构化绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51503114/

相关文章:

c++ - 使用 C++ 在 Linux 中设置系统和硬件时间

c++ - GCC C++ 错误? (T)x 匹配 X::operator const T&() const 与 clang 的不同

c++ - 返回*这个;删除指针

c++ - 为什么 const 临时绑定(bind)到右值引用参数?

c++ - 在安装 NVIDIA CUDA 的同时使用 Intel OpenCL.dll

c++ - 在不使用 C 字符串函数的情况下从 C 字符串中删除元音

c++ - 了解递归以生成排列

c++ - 为什么我下面的第二个片段显示未定义的行为?

c++ - 经过一段时间后,是否有办法从流程中分离流程?

c++ - 您能否根据是否使用返回值来保证不同的生命周期行为?