GCC-Visual Studio std :: thread编译器的差异

时间:2015-08-15 17:29:05

标签: c++ c++11 gcc visual-studio-2013 stdthread

编辑:最后添加了编译器错误。 首先,我说我已经设置并运行了Visual Studio Express 2013和CodeBlocks(Mingw w64)。 但是我遇到了一些使用一个编译器而不是另一个编译器编译的代码的问题,反之亦然。

考虑以下代码:

void foo(std::string& s){
    std::cout << "in foo function now" << std::endl;
    s = "the new string.";
}

int main(){
    std::string s = "the original string";
    std::thread t1(foo, std::ref(s));
    t1.join();

    if (!s.size()) std::cout << "s is empty" << std::endl;
    else std::cout << s << std::endl;

    std::cin.get();
    return 0;
}

它在GCC和VS上编译并运行良好。

但如果我决定用std::ref(s)更改std::move(s),它就不会再用GCC编译了,但它会用VS. 为了解决这个问题,我必须添加一个&#39;&amp;&#39;所以void foo(std::string& s)变为void foo(std::string&& s),然后它将使用gcc进行编译,但它不再使用VS了!

我的猜测是VS编译器是安静的,并没有遵循标准的字母,但即使参数传递,我仍然没有使用std :: function和std :: bind这样的行为就像我相信的那样。

无论如何,我非常感谢帮助理解正在发生的事情。

编辑:错误: 海湾合作委员会一个:

C:/mingw-w64/x86_64-5.1.0-posix-seh-rt_v4-rev0/mingw64/x86_64-w64-mingw32/include/c++/functional:1505:61: error: no type named 'type' in 'class std::result_of<void (*(std::__cxx11::basic_string<char>))(std::__cxx11::basic_string<char>&)>'
       typedef typename result_of<_Callable(_Args...)>::type result_type;
                                                             ^
C:/mingw-w64/x86_64-5.1.0-posix-seh-rt_v4-rev0/mingw64/x86_64-w64-mingw32/include/c++/functional:1526:9: error: no type named 'type' in 'class std::result_of<void (*(std::__cxx11::basic_string<char>))(std::__cxx11::basic_string<char>&)>'
         _M_invoke(_Index_tuple<_Indices...>)

VS一:

Error   1   error C2664: 'void (std::string &&)' : cannot convert argument 1 from 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>' to 'std::string &&' c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional   1149    1   Tests

1 个答案:

答案 0 :(得分:1)

MSVC是错误的,无论是标准还是实际。

在内部,他们都将参数复制到tuple的内容中 - 比如,在生成的线程中解压缩它们并进行调用。

在标准下,invoke表达式必须在复制它们之后将值作为rvalues传递给被调用的函数(除了std::ref个例外)。

这是因为本标准中INVOKE条款的措辞。我在此之前已经谈过这个问题,但还没有跟踪它。

逻辑上,tuple中的值永远不会再次使用,因此它应该在右值上下文而不是左值。按价值取物,复制它,然后通过引用传递它,然后丢弃副本,通常是一个错误。