从外部函数访问外部结构属性

Access external struct attribute from outside function

我在玩一些外部变量,想知道为什么我不能从外部函数访问外部结构?

这是我的代码:

a.h

struct testing {

   unsigned int val;
   const char* str;

   testing(unsigned int aVal, const char* aStr) : val(aVal), str(aStr){};
}

extern testing externalStruct;

a.c

#include "a.h"

testing externalStruct(10, "test");

test.c

#include <iostream>
#include "a.h"

unsigned int valCopy = externalStruct.val;
const char* strCopy = externalStruct.str;

int main()
{
   std::cout<<"Direct val : "<<externalStruct.val<<std::endl; // Working, print 10
   std::cout<<"Direct str : "<<externalStruct.str<<std::endl; // Working, print "test"
   std::cout<<"Copy val : "<<valCopy<<std::endl; // Print 0 instead of 10
   std::cout<<"Copy str : "<<strCopy<<std::endl; // Print nothing

   return 0;
}

有什么想法吗?

未定义全局对象的初始化顺序。

在这种情况下,我猜 valCopystrCopyexternalStruct 的构造函数被调用之前被初始化(=> 用 junk).

如果将 valCopystrCopy 的初始化放入 main 主体中,我相信一切都会正常工作:

int main()
{

   unsigned int valCopy = externalStruct.val;
   const char* strCopy = externalStruct.str;

   std::cout<<"Direct val : "<<externalStruct.val<<std::endl; // Working, print 10
   std::cout<<"Direct str : "<<externalStruct.str<<std::endl; // Working, print "test"
   std::cout<<"Copy val : "<<valCopy<<std::endl; // ??? did it work?
   std::cout<<"Copy str : "<<strCopy<<std::endl; // ??? did it work?

   return 0;
}

编辑

更多信息在这里“C++ global initialization order ignores dependencies?

这个问题是由于静态(全局)变量的初始化顺序未知造成的。它甚至还有一个名字 static initialization order fiasco。这意味着来自 test.c 翻译单元的全局变量在来自 a.c 翻译单元的全局变量之前被初始化。

通常的解决方案是使用带有静态变量的函数。当函数被调用时,静态变量(在第一次使用时)被初始化。使用 c++11 初始化此类静态函数局部变量是线程安全的。

您的代码的解决方案如下所示:

a.h

//...

testing& GetExternalStruct();

a.c

//...

testing& GetExternalStruct() {
   static testing externalStruct(10, "test");
   return externalStruct;
}

test.c

unsigned int valCopy = GetExternalStruct().val;
const char* strCopy = GetExternalStruct().str;

您被 静态初始化顺序失败所欺骗 - C++ 的缺点之一。

两者都

unsigned int valCopy = externalStruct.val;
const char* strCopy = externalStruct.str;

testing externalStruct(10, "test");

main() 执行之前实际调用了

。不幸的是,C++ 没有允许您表达初始化应该以什么顺序进行的语言结构——这或多或少是由编译器随机决定的——在你的情况下,第一个块显然在第二个块之前执行,导致事实当您将值从那里复制到 valCopystrCopy.

时,externalStruct 尚未初始化

您可以通过 将初始化包装 到 return 静态初始化值的函数中来解决此语言缺陷 - 这使您可以控制这些初始化的完成顺序.

a.c:

testing &x() {
   static testing *t = new testing(10, "test");
   return *t;
}

test.c

...
valCopy = x().val;
strCopy = x().str;
...