【问题标题】:Access external struct attribute from outside function从外部函数访问外部结构属性
【发布时间】:2016-06-09 08:32:32
【问题描述】:

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

这是我的代码:

啊。

struct testing {

   unsigned int val;
   const char* str;

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

extern testing externalStruct;

交流

#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;
}

有什么想法吗?

【问题讨论】:

    标签: c++ struct extern


    【解决方案1】:

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

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

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

    啊。

    //...
    
    testing& GetExternalStruct();
    

    交流

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

    test.c

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

    【讨论】:

    • 很高兴我们的两个答案是如此接近 - 不过你比我多几分钟;)
    【解决方案2】:

    你被静态初始化命令惨败所欺骗 - C++ 的缺点之一。

    两个

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

    testing externalStruct(10, "test");
    

    被(并且需要)实际调用之前 main() 被执行。不幸的是,C++ 没有允许您以什么顺序表示初始化应该完成的语言结构 - 这或多或少是由编译器随机决定的 - 在您的情况下,第一个块显然在第二个块之前执行,导致事实当您将值从那里复制到 valCopystrCopy 时,externalStruct 尚未初始化。

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

    交流:

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

    test.c

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

    【讨论】:

      【解决方案3】:

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

      在这种情况下,我猜valCopystrCopy 是在调用externalStruct 的构造函数之前初始化的(=> 用junk 初始化)。

      如果你把valCopystrCopy的初始化放到mainbody里面我相信一切都会正常的:

      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?

      【讨论】:

      • 我在想它可能会使用某种延迟加载,比如调用外部函数。程序知道我们要访问符号“externalStruct”,为什么它无法在复制值之前对其进行初始化?
      • @gagou7 关键是没有“程序”这样的东西知道......程序是你写的东西,然后它通过编译和链接。由于这些全局变量的声明和初始化是在不同的编译单元(不同的文件)中完成的,因此编译器无法强制执行您希望的顺序。更多详情在这里:stackoverflow.com/a/3746249/5218277
      猜你喜欢
      • 2011-03-13
      • 1970-01-01
      • 1970-01-01
      • 2020-01-27
      • 2011-04-15
      • 1970-01-01
      • 2017-05-25
      • 2013-02-23
      • 2013-01-18
      相关资源
      最近更新 更多