c – 与std :: minmax和rvalues的结构化绑定

当使用std :: minmax和结构化绑定时,我遇到了一个相当微妙的错误.似乎传递的rvalues并不总是像人们期望的那样被复制.最初我在自定义容器上使用了T运算符[]()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
}

将GCC 8.1.1与-O1 -Wuninitialized一起使用将导致0,0作为第一行打印,并且:

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

Clang 6.0.1 at -O2也会在没有警告的情况下给出错误的第一个结果.

在-O0 GCC给出正确的结果而没有警告.对于clang,结果在-O1或-O0处显示正确.

在rvalue仍然有效被复制的意义上,第一行和第二行不应该是等价的吗?

另外,为什么这取决于优化级别?特别是我对GCC没有发出任何警告感到惊讶.

解决方法:

在auto [amin,amax]中需要注意的重要一点是auto,auto和amp;等等应用于用std :: minmax的返回值初始化的组成对象e,它是一对.它基本上是这样的:

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时,您正在对现有对象进行赋值(通过引用传递). rvalues不需要比它们产生的赋值表达式更长寿.

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

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));

我们现在得到一份副本,结构化绑定指的是那些副本.

上一篇:事务


下一篇:Spring事务管理