如何解决为什么在c ++中可以在没有#include线程的情况下使用std :: thread?
我在Visual Studio中尝试了https://en.cppreference.com/w/cpp/thread/get_id中的以下代码,并注意到即使没有#include线程,但即使没有#include互斥体,它也可以运行(在注释掉使用了它的行之后):
#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
std::mutex g_display_mutex;
void foo()
{
std::thread::id this_id = std::this_thread::get_id();
g_display_mutex.lock();
std::cout << "thread " << this_id << " sleeping...\n";
g_display_mutex.unlock();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
int main()
{
std::thread t1(foo);
std::thread t2(foo);
t1.join();
t2.join();
}
我想知道为什么,而且我找不到在线解释。互斥锁是否包含线程? IDE的干预?还是其他?
解决方法
编译器标准库中的头之一是内部包含定义std::thread
的头(在您的情况下,<mutex>
包括此头)。
C ++标准仅保证对于任何#include
d标头可见哪些定义 ,但是它不能控制或阻止实现有意或无意地使其他定义从该标题。
之所以会发生这种情况,通常是因为标准库实现中的标头已编写为包含其他内部标头,这些标头可传递这些定义(例如,<mutex>
被编写为包含<internal/thread.hpp>
等)。
依赖于此可传递包含是一种极其糟糕的做法,并且极大地降低了给定程序的可移植性。如果它们更新了内部包含顺序,那么在不同平台,标准库实现甚至相同编译器的不同版本之间移动会变得很复杂。
注意:重要的是要意识到,仅因为标准类型可能与另一个标头中定义的另一个标准类型具有依赖性,它确实不会 确保该标头将被标准库可传递地包括在内,除非C ++标准实际规定了此标头(很少这样做)。
例如,异常std::logic_error
在<stdexcept>
中定义,并派生std::exception
在<exception>
中定义;但是{}并未定义为引入符号#include <stdexcept>
。一些或大多数标准库的实现可以做到这一点;但是标准库在内部进行如下间接操作以防止这种情况发生同样合法:
std::exception
<impl/exception.hpp>
namespace std {
namespace __impl {
class exception { ... };
} // namespace __impl
} // namespace std
<exception>
#include <impl/exception.hpp>
namespace std {
using __impl::exception;
} // namespace std
<impl/stdexcept.hpp>
#include <impl/exception.hpp>
namespace std {
namespace __impl {
class logic_error : public exception { ... }
/* ... other error types ... */
} // namespace __impl
} // namespace std
<stexcept>
从上面的示例中,您可以看到#include <impl/stdexcept.hpp>
namespace std {
// defines 'std::logic_error',and derives 'std::exception',but
// does not define the symbol 'std::exception' (instead,hides it
// under std::__impl::exception)
using __impl::logic_error;
/* ... other error types ... */
} // namespace std
将定义符号#include <stdexcept>
,而不是std::logic_error
,即使这两种类型密切相关。
因此,最好始终遵循“随用随用”(IWYU)做法,即使看起来好像您包括一个冗余标头也是如此。否则,您可能会自行调整当前设置,并为以后的可移植性引入更多的复杂性(即使只是为了升级您的编译器)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。