让我们采用以下代码:
class const_int
{
public:
constexpr const_int(int data) : data_(data) {}
constexpr const_int(const const_int &) = default;
constexpr const_int(const_int &&) = default;
private:
int data_;
};
class test
{
public:
constexpr static const const_int USER = 42;
constexpr static const double NATIVE = 4.2;
};
// constexpr const const_int test::USER;
void pass_by_copie(double)
{
}
void pass_by_copie(const_int)
{
}
void pass_by_const_ref(const const_int&)
{
}
void pass_by_rvalue_ref(const_int&&)
{
}
int main(void)
{
pass_by_copie(test::NATIVE);
pass_by_copie(test::USER);
pass_by_const_ref(test::USER);
pass_by_rvalue_ref(const_int(test::USER));
return (0);
}
以下两行:
pass_by_copie(test::USER);
pass_by_const_ref(test::USER);
在g++ 4.7
下生成以下错误:
对`test :: USER'的未定义引用
我知道没有test::USER
的实例。 (这条线是故意评论的)
我有两个问题:
为什么需要test::USER
的显式实例,而调用函数test::NATIVE
时不需要pass_by_copie
的显式实例?
为什么我可以通过明确地从pass_by_rvalue_ref
创建临时copie来调用test::USER
,而编译器在调用{{{}时无法(或不希望)自己隐式创建相同的copie 1}}与pass_by_copie
?
谢谢
答案 0 :(得分:2)
从C ++ 11的3.2节开始:
名称显示为可能已评估的表达式的变量是 odr-used ,除非它是满足出现在常量表达式中的要求的对象,并且lvalue-to-rvalue转换是立即的应用
和
每个程序应该只包含该程序中使用的每个非内联函数或变量的一个定义
因此定义是必需的,因为test::USER
使用的是odr,并且显然它使用的是odr,因为它不会立即进行左值到右值的转换。令我感到惊讶的是,对pass_by_copie
的调用看起来像是执行左值到右值的转换。
答案 1 :(得分:1)
Clang 4.1给了我这个错误:
Undefined symbols for architecture x86_64:
"test::USER", referenced from:
_main in Untitled-gXrry2.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
我假设这里发生的事情test::NATIVE
可以简单地替换为使用它的值4.2
,并且实际上不需要符号。但是test::USER
作为类的实例而不是标量,确实需要一个符号,以便对test::USER
的所有引用都引用同一个对象。鉴于此,您实际上确实需要显式实例。