我正在使用 C++14 中的新模板变量功能以适应它(也许很快就会这样做,因为似乎某些编译器没有完全实现它)。
现在我想知道模板变量的每个实例在哪里。在我到目前为止所做的测试中,它们似乎在任何静态数据之前被初始化,所以我想知道它们是否被放置在程序的数据段中。让我们看看到目前为止我已经尝试过什么,我有一个类可以打印有关构造和破坏的信息:
struct squealer
{
squealer(std::string a_name) : m_name(a_name) { std::cout << this << ' ' << m_name << ' ' << __PRETTY_FUNCTION__ << '\n'; }
~squealer() { std::cout << this << ' ' << m_name << ' ' << __PRETTY_FUNCTION__ << '\n'; }
void f() {}
const std::string m_name;
};
squealer
还有一个在本地存储、静态存储和模板变量中实例化一些s 的程序,这是该程序:
// static storage squealer
squealer s("\"static\"");
// template variable squealer
template <int i> squealer test(std::string(i, 'A'));
// function using a template variable squealer
void f() { test<1>.f(); }
int main(int argc, char **argv)
{
// local storage squealer
squealer ss("local");
// using another template variable squealers
test<2>.f();
switch (argc)
{
case 1: test<3>.f(); break;
case 2: test<4>.f(); break;
case 3: test<5>.f(); break;
case 4: test<6>.f(); break;
}
return 0;
}
这是程序,这是输出:
A squealer::squealer(std::string)
AA squealer::squealer(std::string)
AAA squealer::squealer(std::string)
AAAA squealer::squealer(std::string)
AAAAA squealer::squealer(std::string)
AAAAAA squealer::squealer(std::string)
"static" squealer::squealer(std::string)
local squealer::squealer(std::string)
local squealer::~squealer()
"static" squealer::~squealer()
AAAAAA squealer::~squealer()
AAAAA squealer::~squealer()
AAAA squealer::~squealer()
AAA squealer::~squealer()
AA squealer::~squealer()
A squealer::~squealer()
正如我们所看到的,所有模板变量squealer
实例都是在命名的之前创建的"static"
,最后(如预期的那样)命名local
的被创建,销毁顺序是相反的(如预期的那样),所以:创建/初始化的顺序模板变量实例的数量与其在代码上的外观相同,无论此外观的位置如何,也无论它们是否被使用(f()
从不调用该函数)。
那么第一个问题是,这个模板变量是放在数据段上的吗?我不知道如何测试或检查它。
第二个问题是,所有这些模板变量squealer
实例都是线程安全的吗?我在n3376 §6.7上阅读了以下句子(强调我的):
允许实现在与允许实现在命名空间范围(3.6.2)中静态初始化具有静态或线程存储持续时间的变量相同的条件下,对具有静态或线程存储持续时间的其他块范围变量执行早期初始化。否则,此类变量在控件第一次通过其声明时被初始化;这样的变量在其初始化完成时被认为已初始化。如果初始化抛出异常退出,说明初始化未完成,下次控件进入声明时会再次尝试。如果控制在变量初始化的同时进入声明,并发执行将等待初始化完成.
从 C++11 开始,如果所有模板变量squealer
实例都在静态存储中,它们应该是线程安全的,不是吗?
谢谢。