Re: [问题] struct static const member link error

楼主: carylorrk (carylorrk)   2015-01-21 12:02:06
※ 引述《shininglion (lionking - 辛巴)》之铭言:
: 开发平台(Platform): (Ex: VC++, GCC, Linux, ...)
: Ubuntu 14.04, g++ v4.8.2
: 问题(Question):
: link error, undefined reference to XXX
: 程式码(Code):(请善用置底文网页, 记得排版)
: 问题程式码如下,分在两个档案
: [fileA.h]
: struct A
: {
: static const int val = 0;
: };
: [fileB.cpp]
: /* something */
: std::unordered_map<int, std::string> umap;
: /* somthing */
: const std::string str = umap.at(A::val) + "123"; // error here
: 上面那行就是我的问题所在
: 因为 A::val 是 A 的 static const member,所以语法上应该是没问题的
: compile 也确实有过,但是 link 时就喷 error 说找不到 A::val
: 后来我把 fileB.cpp 的那一段改成下面这样就过了:
: [fileB.cpp]
: /* something */
: std::unordered_map<int, std::string> umap;
: /* something */
: const int VAL = A::val;
: const std::string str = umap.at(VAL) + "123"; // pass
: 我想不出原因为什么一开始的写法会 link error
: 但是改成下面这种写法就过了
: 想请问有版友知道原因吗?
: 谢谢!
根据标准(2003 版的 9.4.2.4)
If a static data member is of const integral or const enumeration type,
its declaration in the class definition can specify a constant-initializer
which shall be an integral constant expression (5.19). In that case,
the member can appear in integral constant expressions. The member shall
still be defined in a namespace scope if it is used in the program and the
namespace scope definition shall not contain an initializer.
所以最标准的写法是,你应该要在 class 实作的地方(ex:fileA.cpp)加上这行
const int A::val;
至于为什么另外 assign 到其他变量就可行而传进 at 却不行?
我猜是因为 static const int 有可能并没有 allocate memory
at 接收的是一个 reference,当然会找不到。
而另外 assign 或是加上可以产生 temporary variable 的方法都可以绕过。
不过最正确的方法还是明确给他个 definition。
补上 11 标准的 9.4.2.3
If a non-volatile const static data member is of integral or enumeration
type, its declaration in the class definition can specify a
brace-or-equal-initializer in which every initializer-clause that is an
assignment-expression is a constant expression (5.19). A static data member
of literal type can be declared in the class definition with the constexpr
specifier; if so, its declaration shall specify a brace-or-equal-initializer
in which every initializer-clause that is an assignment-expression is a
constant expression. [ Note: In both these cases, the member may appear in
constant expressions. — end note ] The member shall still be defined in a
namespace scope if it is odr-used (3.2) in the program and the namespace
scope definition shall not contain an initializer.
作者: shininglion (lionking - 辛巴)   2015-01-21 16:54:00
谢谢解答,问题已确实解决. 看来以前是运气好没遇到

Links booklink

Contact Us: admin [ a t ] ucptt.com