c++全局变量的延迟示例化

aemubtdh  于 2022-12-15  发布在  其他
关注(0)|答案(4)|浏览(149)

我有一些代码,其中一个全局资源必须设置相当多的代码:

globalClass foo;  // global variable / object; give it a memory space to live

void doSomething( void )
{
  foo.bar();      // use the global foo object
}

int main( int argc, const char *argv[] )
{
  foo( argc );   // foo can only be instantiated in main as it's using
                 // information that's only available here

  doSomething(); // use the global foo object

  return 0;
}

正如您所看到的,foo是全局作用域--但是要调用它的构造函数,我需要一些只有在main内部才能得到的信息。

我如何才能做到

我能想到的唯一解决方案是将foo设置为指向globalClass的指针--但这会导致每次使用foo时指针解引用。
PS:在真实的的程序中,maindoSomething会存在于不同的文件中,当然可以保证foo在示例化之前不会被访问。

gv8xihay

gv8xihay1#

foo作为函数中的static变量怎么样?这样,它只在函数被调用时才被示例化:

globalClass& getThing()
{
  static globalClass thing;
  return thing;
}

void doSomething(const globalClass& thing);

int main()
{
  const globalClass& x = getThing();
  doSomething(x);  
}
ie3xauqp

ie3xauqp2#

像你提到的那样使用指针是最简单和最干净的事情。指针解引用的开销并不是很大。我建议你使用这个方法,除非你已经证明了开销是明显的。
第二个选择是将globalClass的构造和初始化分离成两个独立的方法,构造函数只做不需要外部信息的最简单的事情,然后调用init(argc)main内部的任何东西来合并外部信息。
您也可以使用赋值来初始化foo,例如:

globalClass foo;

int main(int argc, const char *argv[]) {
    globalClass bar(argc);
    foo = bar;
}

这实际上是使用临时变量进行初始化,然后复制结果。

lpwwtiir

lpwwtiir3#

这里有一个非常可怕的黑客,如果你不想间接和不介意自己做清理:

union ClassHolder
{
    globalClass x;
    char buf[sizeof globalClass];

    constexpr ClassHolder() noexcept : buf() { }
};

ClassHolder h;
globalClass & foo = h.x;

int main()
{
    new (static_cast<void *>(&h.x)) globalClass(arg1, arg2, arg3);

    // main program

    h.x.~globalClass();
}
crcmnpdw

crcmnpdw4#

你可以这样做:

globalClass* foo;  
// declare foo as a global pointer to class globalClass. No object instantiated here
    
    void doSomething( void )
    {
      foo->bar();      // use the global foo object pointer
    }
    
    int main( int argc, const char *argv[] )
    {
      foo = new globalClass(); 
      // an object is instantiated from class globalClass and the pointer to that object assigned to foo. This object will not be destroyed when the function who created ends. Parameters for the constructor can the passed inside the ()
    
      doSomething(); // use the global foo object
    
      return 0;
    }

相关问题