Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 控制静态对象的顺序';建造师_C++_Constructor_C++11 - Fatal编程技术网

C++ 控制静态对象的顺序';建造师

C++ 控制静态对象的顺序';建造师,c++,constructor,c++11,C++,Constructor,C++11,我正在用c++11编写一个小型内核,并且有两个相同类型的实例,必须在创建任何其他静态对象之前构建它们 我写的代码如下: // test.hpp class test { // blahblah... }; // test.cpp typedef char fake_inst[sizeof(test)] __attribute__((aligned(alignof(test)))); fake_inst inst1; fake_inst inst2; // main.cpp extern

我正在用c++11编写一个小型内核,并且有两个相同类型的实例,必须在创建任何其他静态对象之前构建它们

我写的代码如下:

// test.hpp
class test {
  // blahblah...
};

// test.cpp
typedef char fake_inst[sizeof(test)] __attribute__((aligned(alignof(test))));

fake_inst inst1;
fake_inst inst2;

// main.cpp
extern test inst1;
extern test inst2;

int kmain() {
    // copy data section

    // initialize bss section

    new (&inst1) test();
    new (&inst2) test();

    // call constructors in .init_array

    // kernel stuffs
}
它按照预期构建和工作,没有任何警告消息,但不支持LTO

我收到了大量的警告消息,抱怨类型匹配,我想知道是否有解决办法,因为它会让我难以找到其他“真实”的警告或错误消息


有什么建议吗?

您能使用GCC的
init\u priority
属性吗

Some_Class  A  __attribute__ ((init_priority (2000)));
Some_Class  B  __attribute__ ((init_priority (543)));
//在.h文件中
typedef char fake_inst[sizeof(test)]__属性(aligned(_alignof__(test)));
外部假冒伪劣;
外部假冒伪劣2;
内联测试&f_inst1(){return*reinterpret_cast(fake_inst1);}
内联测试&f_inst2(){return*reinterpret_cast(fake_inst2);}
//和可读性
静态测试和inst1(f_inst1());
静态测试和inst2(f_inst2());

希望
inst1
f_inst1()
都能得到优化。

C++没有提供管理多个文件中全局对象初始化顺序的方法。如果您需要如此严格地管理这些对象的初始化顺序,那么我强烈建议您不要将它们设置为全局对象。使它们成为包含静态对象并返回指向它们的指针的全局函数

但即便如此,这也没有完全手动初始化那么危险。只需为那些需要它们的人提供一些指向这些对象的指针(最好不是全局指针),您就可以了。

也许像这样

// ... .h
template<typename T>
union FakeUnion {
  FakeUnion() {}
  ~FakeUnion() {}

  T inst;
};

extern FakeUnion<test> inst1_;
extern FakeUnion<test> inst2_;
static constexpr test& inst1 = inst1_.inst;
static constexpr test& inst2 = inst2_.inst;
// ... .h end

// ... .cpp
FakeUnion<test> inst1_;
FakeUnion<test> inst2_;
// ... .cpp end
/。H
模板
联盟伪造联盟{
伪联合(){}
~FakeUnion(){}
T inst;
};
外部伪造联合研究所;
外部伪造联合研究所;
静态constexpr测试&inst1=inst1_u2;inst;
静态constexpr测试&inst2=inst2_u2;inst;
// ... .h端
// ... .cpp
假联合研究所;
伪造联合研究所;
// ... .cpp端

main
中,您可以说
new(&inst1)test。它现在不应该再发出关于类型不一致性冲突的警告,因为与代码中的不同,这段代码不包含在不同文件中具有不同类型的变量。

我读过这方面的内容,但很难管理构造函数的顺序,因为优先级分布在源文件中。@kukyakya所以问题是首先初始化两个对象,或者总体上对所有全局构造函数进行排序?@Potatoswatter实际上,这不仅仅是两个实例,而是同一类型的多个实例,所以我不能使用单例模式。其他静态对象的构造顺序无关紧要。我考虑过使用全局函数返回函数作用域静态对象的引用或指针,但编译器生成acquire/release来创建实例,acquire/release使用内核互斥实现,不能在内核初始化中使用。@kukyakya:那么您必须手动初始化这些对象。这是确保没有内核互斥体的唯一方法。这正是我使用的方法,但我想知道是否有更整洁的方法。我想要像
std::cout
std::cin
这样的全局对象,因为它看起来比实例返回函数更可读。可以尝试全局引用变量,初始化为
inst1
的retval?这也是优化的(在msvc中)全局变量的问题是它们的初始顺序,这就是我们试图解决的…@n.m.:正确点。但在这种特殊情况下,这没关系。引用本身是一个全局变量,它在占位符的
main
之前初始化。您真正想做什么?在下面对Pubby答案的评论中,您说您想初始化几个相同类型的对象。对我来说,似乎您想初始化与C++支持相关的结构,例如堆,然后让实现调用其他构造函数。但这听起来不像你要尝试的。还有,你会得到关于什么类型的“类型匹配”的警告?@Potatoswatter很多
警告:“xxx”的类型与原始声明不匹配[默认启用]
事情。这是因为实际类型不是test,而是char[]。我以为我可以禁用静态构造函数,但似乎没有办法。啊,我明白了。你应该做的是
char fake_inst1[sizeof(test)];测试*const inst1=钢筋混凝土浇筑<测试*>(假inst1)禁用静态构造函数的方法是将变量放入包装函数中。只有在第一次调用包装器时才会调用构造函数。这是非常惯用的方法,总是比在名称空间范围中放置全局名称空间更可取。但是,在您的情况下,您需要确保在运行时支持用于实现“仅第一次”功能的多线程操作。无论您是否找到抑制警告的方法,这都是处理具有非平凡c'tor/d'tor的全局/静态对象的唯一真正正确的方法。这样不仅可以控制它们的初始化/销毁顺序,还可以实际控制程序流。例如,您可以从它们的初始化代码中抛出异常,并适当地捕获它们。所有这些都不会影响性能。虽然这确实解决了名称冲突,但它不能确保在调用任何其他构造函数之前调用
inst1
inst2
。@Matt如果他在
main
中调用它们,并使用新的位置,如果以受控的方式在
main
之后调用所有其他的CTOR,它确实可以确保这一点。您能就这里发生的“魔力”给出建议吗?也就是说,为什么我们需要工会,为什么工会有ctor/dtor?
// ... .h
template<typename T>
union FakeUnion {
  FakeUnion() {}
  ~FakeUnion() {}

  T inst;
};

extern FakeUnion<test> inst1_;
extern FakeUnion<test> inst2_;
static constexpr test& inst1 = inst1_.inst;
static constexpr test& inst2 = inst2_.inst;
// ... .h end

// ... .cpp
FakeUnion<test> inst1_;
FakeUnion<test> inst2_;
// ... .cpp end