Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.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++;全局变量的后期实例化_C++_C++11 - Fatal编程技术网

C++ c++;全局变量的后期实例化

C++ c++;全局变量的后期实例化,c++,c++11,C++,C++11,我有一些代码,其中必须通过相当多的代码设置全局资源: 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

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

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:在真实的程序中,
main
doSomething
将位于不同的文件中。当然,可以保证在实例化之前不会访问
foo

foo
作为函数中的
静态变量如何?这样,它只有在调用函数时才会被实例化:

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

void doSomething(const globalClass& thing);

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

使用您提到的指针是最简单、最干净的方法。指针取消引用的开销实际上没有那么大。我建议你使用这个,除非你已经证明了开销是显而易见的

您的第二个选择是将
globalClass
的构造和初始化分离为两个单独的方法。构造函数只做最简单的事情,不需要外部信息,您可以调用
init(argc)
main
内部的任何东西来合并外部信息

您还可以使用赋值来初始化foo,如:

globalClass foo;

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

这基本上是使用一个临时变量进行初始化,然后复制结果。

如果您不想进行间接寻址,也不介意自己进行清理,那么这里有一个非常糟糕的方法:

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();
}
联合类持有者
{
全局类x;
char buf[全局类的大小];
constexpr ClassHolder()noexcept:buf(){}
};
类别持有人h;
globalClass&foo=h.x;
int main()
{
新的(静态_cast(&h.x))全局类(arg1、arg2、arg3);
//主程序
h、 x.~globalClass();
}

使其成为一个全局函数,返回对静态局部的引用,会不会有那么多的语法负担?如果是这样,如果你已经习惯了全局变量的“邪恶”,为什么不再忍受一个邪恶,只给
globalClass
一个
init
函数而不是依赖构造函数呢?为什么它必须是一个全局变量,而不是
doSomething
的参数呢?语法负担对我来说是可以的,只要它停留在编译时或者安装时(即运行时的第一次迭代)。
init
的想法很好,但很抱歉,我忘了注意到
globalClass
来自一个我并不急于修改的外部库。(顺便说一句:当然,globals被认为是邪恶的——但在像这里这样的受控环境中,对于我来说,这是一个不错的选择,而不是在每个实例中存储一个
globalClass
的副本
doSomething
,这实际上是一个类的方法…)globals只有在没有正确编码的情况下才是邪恶的。但是如果您想避免它们,可以在
main
中创建并初始化对象,并将指向该对象的指针/引用传递给需要访问它的所有函数。您不能调用
foo
的构造函数。您可以调用
globalClass
的构造函数来创建它的实例。在您的
main
中,您正在
foo
中调用
globalClass::operator()
,这是一个
globalClass
实例。+1,此方法还可以防止我处理重线程代码。我们不使用函数static,因为如果两个线程同时进入函数,则无法保证函数static只构造一次。@Brian,我认为这是有保证的。但是如果你想确定,在对象构造完成后,从nmain启动线程,并将其传递给其他人。不过,这很尴尬,因为你需要对象是默认的可构造和可分配的……这个例子没有显示如何像OP ask一样,由
argc
main
中初始化
globalClass
,常量引用也不会让你这么做。@LightnessRacesinOrbit:我想把它称为“联合黑客”:-)好了:P尽管实际上我想知道
buf
的初始化是否算作写入…@LightnessRacesinOrbit:那没关系,因为我们以后会覆盖它。@LightnessRacesinOrbit:嘿,难道没有一个子句表明指向任何工会成员的指针是相同的吗?也许我的原始版本还可以…不,因为你仍然在写
buf
,然后从
x
读取。也许吧。这是一个不错的解决方案,但有时它不起作用:您需要一个默认构造函数和赋值运算符(或复制运算符)。如果
globalClass
没有这些,它将无法工作。但在许多情况下,这是一个很好的解决方案,在安装期间只会产生一点开销,但在运行期间是免费的。