GCC-Visual Studio std::线程编译器的差异
GCC-Visual Studio std::thread compiler differences
编辑:在末尾添加了编译错误。首先,我会说我已经设置并运行了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编译,但它将与VS。为了修复它,我必须添加一个'&',所以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...>)
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.0vcincludefunctional 1149 1 Tests
MSVC是错误的,既不符合标准,也不符合实际。
在内部,它们都将参数复制到类似tuple
的东西中,在派生线程中解包它们并进行调用。
在标准下,调用表达式必须在复制后将值作为右值传递给被调用函数(好吧,除了std::ref
的情况)。
这是因为本标准中INVOKE
条款的措辞。我以前在这里说过,但是还没有找到。
逻辑上,tuple
中的值永远不会再被使用,所以它应该在右值上下文中,而不是左值上下文中。按值获取某物,复制它,然后通过引用传递它,然后抛出副本,这通常是一个bug。
相关文章:
- 从不同线程使用int64的不同字节安全吗
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 在C++中使用cURL和多线程
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 我怎么知道C++编译器是否制作线程安全的静态对象代码
- 在Windows 10上使用C 中的线程(使用G 作为编译器)的问题
- 尝试使用std ::线程时编译器错误
- 编译器优化是否解决了线程安全问题
- 可以(通过编译器)使用多少个线程来初始化全局对象(函数main之前)
- STD线程呼叫模板模板类的成员功能:编译器错误
- C++编译器中的线程
- 对于 c++11 之前的编译器,返回本地静态对象线程是否安全
- 计时器、线程和编译器不当行为
- 线程池的 lambda 函数内的编译器错误变量"未捕获"
- C++编译器:为不同线程整理的接口
- 多线程可能会抑制编译器优化
- GCC-Visual Studio std::线程编译器的差异
- 现在的C和C++编译器的线程保证是什么
- C++ 编译器如何保证常量成员变量的线程安全
- visual studio 2010 -是否有办法在旧的C/ c++编译器中使用c++ 11线程对象?