编辑:在最后添加了编译器错误。 首先,我会说我同时设置并运行了 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/