我想static const char在班上有一个数组.海湾合作委员会抱怨并告诉我应该使用constexpr,虽然现在它告诉我这是一个未定义的参考.如果我使数组成为非成员,那么它将编译.到底是怎么回事?
// .hpp
struct foo {
void bar();
static constexpr char baz[] = "quz";
};
// .cpp
void foo::bar() {
std::string str(baz); // undefined reference to baz
}
Run Code Online (Sandbox Code Playgroud) 我对static constexprC++ 11中的成员变量有一些疑惑.
template<typename T>
struct cond_I
{ static constexpr T value = 0; };
// specialization
template<typename T>
struct cond_I< std::complex<T> >
{ static constexpr std::complex<T> value = {0,1}; };
Run Code Online (Sandbox Code Playgroud)
cout << cond_I<double>::value << endl; // this works fine
cout << cond_I< complex<double> >::value << endl; // linker error
Run Code Online (Sandbox Code Playgroud)
但是,如果我添加以下行,first.hpp一切正常.
template<typename T1>
constexpr std::complex<T1> cond_I< std::complex<T1> >::value;
Run Code Online (Sandbox Code Playgroud)
我理解的(我可能是错的)是,cond_I< std::complex<double> >::value需要一个定义,但在前一种情况下它只有声明.但那又怎么样cond_I<double>::value?为什么它不需要定义?
再次,在另一个头文件中second.hpp,我有:
// empty struct
template<typename T> …Run Code Online (Sandbox Code Playgroud) 为什么下面的工作原理gcc却没有clang,(现场观看):
constexpr int giveMeValue() { return 42; }
struct TryMe {
static constexpr int arr[1] = {
giveMeValue()
};
};
int main() {
int val = TryMe::arr[0];
return val;
}
Run Code Online (Sandbox Code Playgroud)
我得到一个未解决的外部符号与clang.
是TryMe::arr[0]一个对象?如果是的话,它是否经常使用?
是否可以使用编译器命令行选项来防止静态const成员优化?
这是一个例子:
template <unsigned v1>
struct TRAITS {
static const unsigned val1 = v1;
};
template < class TRAITS >
struct foo {
static const unsigned x1 = TRAITS::val1;
};
int main () {
foo<TRAITS<1>> f1;
// SET BREAKPOINT HERE
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译:
g++ -g -O0 optimize_out.cpp
Run Code Online (Sandbox Code Playgroud)
GDB:
gdb a.out
(gdb) break optimize_out.cpp:13
(gdb) r
(gdb) p f1
$1 = {static x1 = <optimized out>}
Run Code Online (Sandbox Code Playgroud)
这段代码的具体内容是类是模板.可能在C++标准中有一些东西迫使编译器优化字段,即使使用-O0?当我不使用模板时,值不会被优化:
struct foo {
static const unsigned x1 = 1;
};
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我可以在调试器中看到x1
举个例子:
#include <iostream>
class A
{
public:
static const int numberOfWheels = 4;
};
// const int A::numberOfWheels;
int main()
{
std::cout << A::numberOfWheels << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
难道是正式未定义行为(UB),因为A::numberOfWheels是使用没有它的定义是什么?(另见这里).正如C++ 03所述:
如果在程序中使用该成员,并且名称空间范围定义不包含初始化程序,则该成员仍应在名称空间作用域中定义.
我发现在C++ 03 中使用的定义相当混乱,因为它指向可能被评估的表达式:
如果对象或非重载函数的名称出现在可能已评估的表达式中,则使用该函数.
从我的猜测来看,它排除了以下表达式:
sizeof(A::numberOfWheels) ;
typeid(A::numberOfWheels).name() ;
Run Code Online (Sandbox Code Playgroud)
但不一定是<<像上面那样重载运算符的表达式.