我正在玩外部变量,并想知道为什么我无法从外部函数访问外部结构?
这是我的代码:
A.H
'\n'
交流转换器
struct testing {
unsigned int val;
const char* str;
testing(unsigned int aVal, const char* aStr) : val(aVal), str(aStr){};
}
extern testing externalStruct;
test.c的
#include "a.h"
testing externalStruct(10, "test");
有什么想法吗?
答案 0 :(得分:2)
此问题是由于静态(全局)变量的初始化顺序未知而引起的。它甚至有一个名字static initialization order fiasco。这意味着来自test.c转换单元的全局变量在来自a.c转换单元的全局变量之前初始化。
通常的解决方案是使用带有静态变量的函数。调用函数时,初始化静态变量(在首次使用期间)。使用c ++ 11初始化这种静态函数,局部变量是线程安全的。
您的代码的解决方案可能如下所示:
A.H
//...
testing& GetExternalStruct();
交流转换器
//...
testing& GetExternalStruct() {
static testing externalStruct(10, "test");
return externalStruct;
}
test.c的
unsigned int valCopy = GetExternalStruct().val;
const char* strCopy = GetExternalStruct().str;
答案 1 :(得分:1)
你被静态初始化命令fiasco 欺骗 - 这是C ++的一个缺点。
两者
unsigned int valCopy = externalStruct.val;
const char* strCopy = externalStruct.str;
和
testing externalStruct(10, "test");
在 main()
执行之前,(并且需要)实际上被称为。不幸的是,C ++没有语言结构允许你按照初始化的顺序表达 - 这是由编译器随机决定的 - 在你的情况下,第一个块显然在第二个块之前执行,导致事实当您将值从externalStruct
和valCopy
复制到strCopy
时,testing &x() {
static testing *t = new testing(10, "test");
return *t;
}
尚未初始化。
您可以通过将初始化包装到返回静态初始化值的函数中来解决此语言缺陷 - 这使您可以控制初始化的顺序。
交流转换器:
...
valCopy = x().val;
strCopy = x().str;
...
test.c的
<!doctype html>\r\n
<html>
\r\n
<head>
\r\n
<meta name=\"viewport\" content=\"width=device-width\">
\r\n
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">
\r\n
<title>Really Simple HTML Email Template</title>
\r\n
<style>\r\n/* -------------------------------------\r\n GLOBAL\r\n------------------------------------- */\r\n* {\r\n font-family: \"Helvetica Neue\", \"Helvetica\", Helvetica, Arial, sans-serif;\r\n font-size: 100%;\r\n line-height: 1.6em;\r\n margin: 0;\r\n padding: 0;\r\n}\r\nimg {\r\n max-width: 600px;\r\n width: auto;\r\n}\r\nbody {\r\n -webkit-font-smoothing: antialiased;\r\n height: 100%;\r\n -webkit-text-size-adjust: none;\r\n width: 100% !important;\r\n}\r\n/* -------------------------------------\r\n ELEMENTS\r\n------------------------------------- */\r\na {\r\n color: #348eda;\r\n}\r\n.btn-primary {\r\n Margin-bottom: 10px;\r\n width: auto !important;\r\n}\r\n.btn-primary td {\r\n background-color: #348eda;\r\n border-radius: 10px;\r\n font-family: \"Helvetica Neue\", Helvetica, Arial, \"Lucida Grande\", sans-serif;\r\n font-size: 14px;\r\n text-align: center;\r\n vertical-align: top;\r\n}\r\n.btn-primary td a {\r\n background-color: #348eda;\r\n border: solid 1px #348eda;\r\n border-radius: 25px;\r\n border-width: 7px 20px;\r\n display: inline-block;\r\n color: #ffffff;\r\n cursor: pointer;\r\n font-weight: bold;\r\n line-height: 2;\r\n text-decoration: none;\r\n}\r\n.last {\r\n margin-bottom: 0;\r\n}\r\n.first {\r\n margin-top: 0;\r\n}\r\n.padding {\r\n padding: 10px 0;\r\n}\r\n/* -------------------------------------\r\n BODY\r\n------------------------------------- */\r\ntable.body-wrap {\r\n padding: 20px;\r\n width: 100%;\r\n}\r\ntable.body-wrap .container {\r\n border: 1px solid #f0f0f0;\r\n}\r\n/* -------------------------------------\r\n FOOTER\r\n------------------------------------- */\r\ntable.footer-wrap {\r\n clear: both !important;\r\n width: 100%;\r\n}\r\n.footer-wrap .container p {\r\n color: #666666;\r\n font-size: 12px;\r\n\r\n}\r\ntable.footer-wrap a {\r\n color: #999999;\r\n}\r\n/* -------------------------------------\r\n TYPOGRAPHY\r\n------------------------------------- */\r\nh1,\r\nh2,\r\nh3 {\r\n color: #111111;\r\n font-family: \"Helvetica Neue\", Helvetica, Arial, \"Lucida Grande\", sans-serif;\r\n font-weight: 200;\r\n line-height: 1.2em;\r\n margin: 40px 0 10px;\r\n}\r\nh1 {\r\n font-size: 36px;\r\n}\r\nh2 {\r\n font-size: 28px;\r\n}\r\nh3 {\r\n font-size: 22px;\r\n}\r\np,\r\nul,\r\nol {\r\n font-size: 14px;\r\n font-weight: normal;\r\n margin-bottom: 10px;\r\n}\r\nul li,\r\nol li {\r\n margin-left: 5px;\r\n list-style-position: inside;\r\n}\r\n/* ---------------------------------------------------\r\n RESPONSIVENESS\r\n------------------------------------------------------ */\r\n/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */\r\n.container {\r\n clear: both !important;\r\n display: block !important;\r\n Margin: 0 auto !important;\r\n max-width: 600px !important;\r\n}\r\n/* Set the padding on the td rather than the div for Outlook compatibility */\r\n.body-wrap .container {\r\n padding: 20px;\r\n}\r\n/* This should also be a block element, so that it will fill 100% of the .container */\r\n.content {\r\n display: block;\r\n margin: 0 auto;\r\n max-width: 600px;\r\n}\r\n/* Let's make sure tables in the content area are 100% wide */\r\n.content table {\r\n width: 100%;\r\n}\r\n</style>
\r\n
</head>
\r\n\r\n
<body bgcolor=\"#f6f6f6\">
\r\n\r\n<!-- body -->\r\n
<table class=\"body-wrap\" bgcolor=\"#f6f6f6\">
\r\n
<tr>
\r\n
<td></td>
\r\n
<td class=\"container\" bgcolor=\"#FFFFFF\">
\r\n<!-- content -->\r\n
<div class=\"content\">
\r\n
<table>
\r\n
<tr>
\r\n
<td>
\r\n
<center>\r\n <img src=\"logo-about.jpg\" />\r\n </center>
\r\n
</td>
\r\n
</tr>
\r\n \r\n\r\n
<tr>
\r\n
<td>
\r\n
<center>
\r\n
<h1>Password Reset</h1>
\r\n <br>\r\n
<p>\r\n <b>Username:</b> Larissa<br>\r\n <b>New Password:</b> dsFCPrsn\r\n </p>
\r\n <br>\r\n\r\n <!-- button -->\r\n
<table class=\"btn-primary\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">
\r\n
<tr>
\r\n
<td>\r\n <a href=\"http://localhost:29870/auth/login\">Login</a>\r\n </td>
\r\n
</tr>
\r\n
</table>
\r\n
</center>
\r\n
</td>
\r\n
</tr>
\r\n\r\n\r\n
</table>
\r\n
</div>
\r\n <!-- /content -->\r\n\r\n
</td>
\r\n
<td></td>
\r\n
</tr>
\r\n
</table>
\r\n<!-- /body -->\r\n\r\n<!-- footer -->\r\n
<table class=\"footer-wrap\">
\r\n
<tr>
\r\n
<td></td>
\r\n
<td class=\"container\">\r\n\r\n\r\n </td>
\r\n
<td></td>
\r\n
</tr>
\r\n
</table>
\r\n<!-- /footer -->\r\n\r\n
</body>
\r\n
</html>
答案 2 :(得分:0)
未定义全局对象的初始化顺序。
在这种情况下,我猜在valCopy
的构造函数被调用(=&gt;使用 junk 初始化)之前初始化了strCopy
和externalStruct
。 / p>
如果您将valCopy
和strCopy
的初始化放入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?”