gcc和msvc(或Linux和Windows)中的valarray有啥区别

Posted

技术标签:

【中文标题】gcc和msvc(或Linux和Windows)中的valarray有啥区别【英文标题】:What are the differences of valarray in gcc and msvc (or Linux and Windows)gcc和msvc(或Linux和Windows)中的valarray有什么区别 【发布时间】:2014-11-12 09:49:18 【问题描述】:

我在 Windows 和 Linux 中体验到 valarray 的不同行为。有谁知道这个或知道在哪里看?很明显,在这两个系统上运行的一个版本是正确的 C++,但为什么另一个在 Windows 上工作? valarray的实现还有更多区别吗?

适用于 MSVC/Windows 但不适用于 gcc/Linux 的代码示例:

    valarray<signed short> myValues;
    for(size_t s = 0; s < 10; s++)
    
        slice dataSlice(1, 1, 1);
        // on Linux, this slice operation gives me a segmentation fault
        myValues= RawData[dataSlice];
    

我跟踪它以修复 gcc/Linux 版本的代码:

    for(size_t s = 0; s < 10; s++)
    
        slice dataSlice(1, 1, 1);
        valarray<signed short> myValues = RawData[dataSlice];
    

gcc/Linux 版本要求 l-value (myValues) 已经初始化。这在 MSVC/Windows 上似乎没有必要。我可以在 Linux 上调用 myValues.resize(1),它也能正常工作。

现在,有人知道确切的差异或互联网上的资源吗?是否有如何使用 valarray 的最佳实践?

软件版本:

Windows 7、MS Visual Studio 2010 SP1、Visual C++ 编译器 16.00.40219.01 for 80x86 Lubuntu 14.04 64 位虚拟机,GNU Make 3.81,GCC 4.8.2

谢谢大家。


更新:详细的代码示例。 可以编译。第一个示例在 Linux 中出现分段错误,但在 Windows 中运行良好。

// This example compiles both on Windows with MSVC and on Linux with GCC.
// It gives a segmentation fault in Linux.
// It gives the expected output on Windows.

#include "stdafx.h"

#include <iostream>
#include <valarray>

int main(int argc, char **argv) 

  //init base data

  std::valarray<signed short> myData(10);
  for (int i = 0; i < 10; i++)
  
    myData[i] = i;
  

  std::valarray<signed short> myValues;

  for (int i = 0; i < 10; i++)
  
    myValues = myData[std::slice(0, i, 1)];
    std::cout << "myValues: ";

    for (size_t k = 0; k < myValues.size(); k++)
      
        std::cout << myValues[k] << ",";
    

    std::cout << std::endl;
  

以下示例在 Linux 和 Windows 上运行良好。注意 for 循环中 myValues 的声明和初始化,就在切片完成的地方。

#include "stdafx.h"

#include <iostream>
#include <valarray>

int main(int argc, char **argv) 

  //init base data

  std::valarray<signed short> myData(10);
  for (int i = 0; i < 10; i++)
  
    myData[i] = i;
  

  for (int i = 0; i < 10; i++)
  
    std::valarray<signed short> myValues = myData[std::slice(0, i, 1)];
    std::cout << "myValues: ";

    for (size_t k = 0; k < myValues.size(); k++)
      
        std::cout << myValues[k] << ",";
    

    std::cout << std::endl;
  

预期输出:

myValues:
myValues: 0,
myValues: 0,1,
myValues: 0,1,2,
myValues: 0,1,2,3,
myValues: 0,1,2,3,4,
myValues: 0,1,2,3,4,5,
myValues: 0,1,2,3,4,5,6,
myValues: 0,1,2,3,4,5,6,7,
myValues: 0,1,2,3,4,5,6,7,8,

【问题讨论】:

能不能做一个完整的可以编译的例子?另外,您使用的是哪个版本的 g++? @MatsPetersson 完成,感谢评论。 【参考方案1】:

valarray.assign/8:

valarray<T>& operator=(const slice_array<T>&);
valarray<T>& operator=(const gslice_array<T>&);
valarray<T>& operator=(const mask_array<T>&);
valarray<T>& operator=(const indirect_array<T>&);

要求:参数引用的数组长度等于size()

您将myValues 创建为大小为0 的空valarray。不满足使用valarray&lt;T&gt;&amp; operator=(const slice_array&lt;T&gt;&amp;); 的先决条件。

替换

myValues = myData[std::slice(0, i, 1)];

auto s = std::slice(0, i, 1);
myValues.resize(s.size());
myValues = myData[s];

myValues = std::valarray<signed short>(myData[std::slice(0, i, 1)]);

它会起作用的。

我还不明白为什么选择slice_array&lt;T&gt; operator[](slice slicearr) 而不是valarray&lt;T&gt; operator[](slice slicearr) const

【讨论】:

是的,我也看过文档 sn-p。我很清楚,为什么它不起作用。但我的问题是:为什么从 Windows 到 Linux 的行为不同,系统之间的其他差异在哪里? Microsoft 标准库实现调整valarray&lt;T&gt;&amp; operator=(const slice_array&lt;T&gt;&amp;); 中的数组大小,这不是标准要求的。奇怪的是,myValues.resize(1) 对所有情况都有帮助,我认为对于更大尺寸的数组也会失败。 这似乎很明显。 “为什么选择slice_array&lt;T&gt; operator[](slice slicearr) 而不是valarray&lt;T&gt; operator[](slice slicearr) const”是什么意思? valarray&lt;T&gt;::operator[] 在表达式 myData[std::slice(0, i, 1)] 中被调用。有两个重载 - const 一个返回 valarray,非 const 一个返回 slice_array。如果选择了第一个,则您不必在分配前调整目标 valarray 的大小。 我正在使用valarray 因为slice_array 只是一个中间类型,我认为不创建对中间类型的引用更干净。我不知道这是否真的很重要。

以上是关于gcc和msvc(或Linux和Windows)中的valarray有啥区别的主要内容,如果未能解决你的问题,请参考以下文章

msvc MinGW gcc g++关系

C++ - 在 Windows 上使用 GCC 而不是 MSVC 值得吗? [关闭]

功能无法匹配GLDEBUGPROC,仅在MSVC上(使用相同的glew版本2.1.0,在linux上使用gcc / clang就可以了)

GCC 和 clang 上的 MSVC /Zp 替代方案是啥?

C++ 指针使用 Visual Studio 更改地址,而不是使用 OsX 中的 Xcode 或 Linux 中的 gcc

使用 gcc 和 msvc 工具集生成的库