c++ - Visual C++ 2017错误?编译器优化表达式

标签 c++ visual-c++ visual-studio-2017 compiler-bug

以下代码段引起了我一些问题,尤其是对diff的评估:

#include <iostream>

template<typename T>
class array2d
{
protected:
    T* arr;
    int w, h;

public:
array2d() : arr(nullptr), w(0), h(0) {}

bool init(int w, int h)
{
    free();
    arr = new (std::nothrow) T[w*h];
    if (arr == nullptr)
    {
        std::cerr << "array2d::init(): Failed to allocate: " << w * h * sizeof(T) << " bytes.\n";
        return false;
    }
    this->w = w;
    this->h = h;
    return true;
}

void fill(T v)
{
    for (int i = 0; i < w*h; ++i)
        arr[i] = v;
}

void free()
{
    if (arr != nullptr)
    {
        delete[] arr;
        arr = nullptr;
        w = 0;
        h = 0;
    }
}

template<typename U>
bool copy(const array2d<U>& v)
{
    if (!v)
    {
        std::cerr << "array2d::copy(): Input array is empty.\n";
        return false;
    }
    if (w*h != v.width()*v.height())
    {
        if (!init(v.width(), v.height())) return false;
    }
    for (int i = 0; i < w*h; ++i)
        arr[i] = static_cast<T>(v(i));
    return true;
}

inline T operator()(int i) const { return arr[i]; }
inline T& operator()(int i) { return arr[i]; }
inline T operator[](int i) const { return arr[i]; }
inline T& operator[](int i) { return arr[i]; }
inline T operator()(int x, int y) const { return arr[x + y*w]; }
inline T& operator()(int x, int y) { return arr[x + y*w]; }

inline int width() const { return w; }
inline int height() const { return h; }
inline const T* get() const { return arr; }
inline T* get() { return arr; }

operator bool() const { return arr != nullptr; }

array2d<T>& operator*=(T v)
{
    for (int i = 0; i < w*h; ++i)
        arr[i] *= v;
    return *this;
}

~array2d() { free(); }
};

typedef unsigned long long uint64;

uint64 computeErrors(const array2d<uint64>& a, const array2d<uint64>& b)
{
    uint64 MNE = 0;
    for (int i = 0; i < a.height()*a.width(); ++i)
    {
        uint64 diff = ((a[i] >= b[i]) ? a[i] - b[i] : b[i] - a[i]);
        if (a[i] != b[i])
        {
            std::cout << "Diff: " << diff << "\n";
            std::cout << "What diff should equal to: " << ((a[i] >= b[i]) ? a[i] - b[i] : b[i] - a[i]) << "\n";
        }
        if (i == 0)
        {
            std::cout << "Diff should not be 0, but it is: " << diff << "\n";
        }
        if (MNE < diff)
        {
            MNE = diff;
            std::cout << "We should reach this, but we don't.\n";
        }
    }
    return MNE;
}



int main()
{
    int w = 1;
    int h = 1;
    array2d<uint64> a;
    if (!a.init(w,h)) return 1;
    a.fill(0);
    array2d<uint64> b;
    if (!b.init(w,h)) return 1;
    b.fill(0);
    a[0] = 0ull;
    b[0] = 1;
    std::cout << a[0] << " " << b[0] << "\n";
    auto e = computeErrors(a, b);
    std::cout << "MNE: " << e << "\n";

    return 0;
}

如果我用/ O1或/ O2或/ Ox进行编译;如果使用/ Ot和/ Ob2,则diff始终为0,而​​不应该为0。如果我在没有/ Ot或没有/ Ob2的情况下进行编译,那么一切都会按预期进行。这段代码中有什么格式错误的内容吗?我将整个内容附在此处:http://coliru.stacked-crooked.com/a/245f23f05df39418。但是,如果我更改数组的[]运算符以返回const T&而不是T,则一切正常。这是编译器错误吗?还是在operator []中返回T而不是const T&是我的坏处(我返回T是因为我读到某个地方,按值传递较小的POD更快,在我的情况下,我有一些uint32数组,其中速度非常重要)。我当前正在使用Visual C++ 2017。

编辑:
按照user4581301的建议,我也在此处添加了整个代码。

编辑2:
这是我的_MSC_FULL_VER:191125547。

最佳答案

该报告于2018年2月28日提交给Visual Studio Developer Community(我假设由@lightxbulb提交)。

在2018年5月8日,据报道(相同的链接),该问题已在最新的Visual Studio版本2017 15.7中解决(根据post header 中的信息)。

关于c++ - Visual C++ 2017错误?编译器优化表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49036542/

相关文章:

c - Visual Studio 似乎将 header 编译为 .c 文件

c++ - 转换透明 png 会使 SDL/OpenGL 崩溃

c++ - 使用字符串赋值和复合赋值安全吗?

javascript - 如何链接使用 emcc 从 cpp 文件编译的 .bc 文件和项目符号库?

c++ - 如何在函数内部操作 char 数组(字符串)的指针,它在 c/c++ 中作为参数传递

c++ - 将 char 数组的最后 8 个字节设置为 __uint64

c++ - 假设规则和移除分配

c++ - 有没有办法在旧版 C/C++ 编译器中使用 C++ 11 线程对象

c# - 获取 "Tuple element name is inferred. Please use language version 7.1 or greater to access an element by its inferred name."

mysql - 使用 F# 连接到 Visual Studio 2017 中的 MySQL 数据库