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

标签 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::move(s) 改变 std::ref(s) 它就不会再用 GCC 编译了但是它会用对比。 要修复它,我必须添加一个 '&' 以便 void foo(std::string& s) 变为 void foo(std::string&& s),然后它将编译使用 gcc,但不再使用 VS!

我的猜测是 VS 编译器是安静宽容的并且没有严格遵守标准但是我没有使用 std::function 和 std::bind 进行这种行为,即使参数传递相同我相信的方式。

无论如何,如果您能帮助我理解正在发生的事情,我将不胜感激。

编辑:错误: GCC 之一:

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

对比:

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

最佳答案

MSVC 在标准和实践中都是错误的。

在内部,它们都将参数复制到类似元组的东西中,然后在生成的线程中解压它们并进行调用。

根据标准,调用表达式必须在复制值后将值作为右值传递给被调用函数(好吧,std::ref 情况除外)。

这是因为该标准中 INVOKE 子句的措辞。我之前在这里谈过它,但还没有找到它。

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

关于c++ - GCC-Visual Studio std::thread 编译器差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32027341/

相关文章:

c++ - 这些情况有什么区别?我怎么知道什么是临时对象?

c++ - 链表深拷贝构造函数

c# - 在 C# 中处理 char*(strlen 函数?)

c++ - 为什么 GDI+ 颜色会根据工具提示是否可见而变化?

c++ - 有没有办法不杀死抛出 std::bad_alloc 的 Qt 应用程序?

c - 删除对 printf 内置函数的引用

c++ - GCC 导致 lambda 捕获的参数包的段错误

c++ - 有谁知道 "-FC"选项在 gcc g++ 中的作用?

c++ - 当前路径的 loadlibrary 失败,GetLastError() == 0

c++ - 我可以在不使用 new 关键字的情况下以某种方式实现它吗? C++