[英]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.0\vc\include\functional 1149 1 Tests
無論是在標准上還是在實踐上,MSVC都是錯誤的。
在內部,它們都將參數復制到類似tuple
的東西中,將它們解壓縮到生成的線程中並進行調用。
根據標准,調用表達式在復制它們之后必須將這些值作為右值傳遞給被調用的函數(好,除了std::ref
情況)。
這是因為該標准中INVOKE
子句的措辭。 在此之前,我已經談論過它,但是還沒有找到它。
從邏輯上講, tuple
的值永遠不會再使用,因此它應該在右值上下文中而不是左值上下文中。 按值獲取某些東西,將其復制,然后按引用傳遞,然后扔掉副本,通常是一個錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.