以下是一个极小的例子,有时会产生警卫,有时却不会:
struct A {
inline A(int v = 0) {} // without ctors, guards are omitted
int m1() const {
return m;
}
private:
int m = 0;
};
//namespace { // without anon-ns guards are generated
template<typename T>
struct X {
static int foo() {
// static T m; // even as local-static and -fno-threadsafe-statics, guards are generated
return m.m1();
}
inline static T m; // comment this and uncomment above to try as local-static
};
//}
int main() {
return X<A>::foo();
}概括地说:
m成为foo()中的静态本地仍然会生成警卫(使用-fno-threadsafe-statics) (在上面的示例中,注释/取消注释适当的行)那么,如何避免在A类中生成一个ctor而不可能使用anon呢?
发布于 2019-10-09 16:24:08
压制警卫的关键是警察和警察:
#include <cstdint>
struct A {
inline constexpr A(uint8_t v) : m{v} {} // without constexpr it should not compile, but does anymay
auto m1() const {
return m;
}
private:
uint8_t m{0};
};
template<typename T>
struct X {
static auto foo() {
return m.m1();
}
constinit inline static T m{2}; // requires constexpr ctor
};
int main() {
return X<A>::foo();
}对于constinit,初始化必须在编译时执行,因此不需要生成保护程序。这需要一个constexpr命令器。在上面的示例中,可以在不使用constexpr的情况下声明ctor (至少对于gcc而言),但这可能是一个挂起的错误。
发布于 2019-10-08 19:00:08
您可以将A的构造函数声明为constexpr,以便静态初始化X<A>::m。
如果需要动态初始化变量,则必须使用保护来防止多次初始化。
如果动态初始化函数范围的静态变量或具有模糊链接的静态数据成员(即类模板的静态数据成员),则有一个相关的保护变量,用于保证构造只发生一次。
发布于 2019-10-09 16:47:42
inline变量由包含其定义的每个转换单元初始化。没有这个保护,每个翻译单元将重新初始化完全相同的变量。
显然,constexpr构造函数使初始化变得静态,因此它不需要运行时初始化.但是,使用动态初始化的对象需要保护。
https://stackoverflow.com/questions/58289965
复制相似问题