Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 这是为什么;无效的C++&引用;_C++ - Fatal编程技术网

C++ 这是为什么;无效的C++&引用;

C++ 这是为什么;无效的C++&引用;,c++,C++,我正在阅读gtest的介绍,发现这部分令人困惑: 编译器抱怨对某些静态对象的“未定义引用” 常量成员变量,但我在类主体中定义了它们。 怎么了? 如果您的类具有静态数据成员: // foo.h class Foo { ... static const int kBar = 100; }; 您还需要在foo.cc中的类主体之外定义它: const int Foo::kBar; // No initializer here. 否则,您的代码是无效的C++,可能会意外中断 方式。特别是,在

我正在阅读gtest的介绍,发现这部分令人困惑:

编译器抱怨对某些静态对象的“未定义引用” 常量成员变量,但我在类主体中定义了它们。 怎么了?

如果您的类具有静态数据成员:

// foo.h
class Foo {
  ...
  static const int kBar = 100;
};
您还需要在foo.cc中的类主体之外定义它:

const int Foo::kBar;  // No initializer here.
否则,您的代码是无效的C++,可能会意外中断 方式。特别是,在Google测试比较断言中使用它 (EXPECT_EQ等)将生成“未定义引用”链接器错误


有人可以解释为什么在类中定义静态const而不在类体外定义它是非法的C++(?)/p> < p>标准基本上说即使你可以在头中给出一个值,如果静态变量是“已使用”的,你仍然必须在源文件中定义它。

在此上下文中,“使用”通常理解为程序的某个部分需要实际内存和/或变量地址


google测试代码很可能在某个点上获取变量的地址(或以其他等效方式使用它)。

标准基本上规定,即使您可以在标题中给出一个值,但如果静态变量“已使用”,您仍必须在源文件中定义它

在此上下文中,“使用”通常理解为程序的某个部分需要实际内存和/或变量地址


最有可能的是,google测试代码在某个点获取变量的地址(或以其他等效方式使用它)。

首先,在类主体内部不是定义,而是声明。声明指定常量的类型和值,定义保留存储空间。例如,如果仅将该值用作编译时常量,则可能不需要存储空间。在这种情况下,代码完全合法的C++。但是,如果您通过引用传递常量,或者使指针指向常量,那么您也需要存储。在这些情况下,您将得到一个“undefined reference”错误。

首先,类主体内部不是定义,而是声明。声明指定常量的类型和值,定义保留存储空间。例如,如果仅将该值用作编译时常量,则可能不需要存储空间。在这种情况下,代码完全合法的C++。但是,如果您通过引用传递常量,或者使指针指向常量,那么您也需要存储。在这些情况下,您将得到一个“undefined reference”错误。

大致上:在类定义中,
static const int kBar=100告诉编译器“Foo将有一个kBar常量(我保证总是100)”。但是,编译器还不知道该变量在哪里。在foo.cc文件中,const int foo::kBar告诉编译器“好的,在这个位置生成kBar”。否则,链接器将查找kBar,但在任何地方都找不到它。

大致上:在类定义中,
static const int kBar=100告诉编译器“Foo将有一个kBar常量(我保证总是100)”。但是,编译器还不知道该变量在哪里。在foo.cc文件中,const int foo::kBar告诉编译器“好的,在这个位置生成kBar”。否则,链接器会去寻找kBar,但在任何地方都找不到它。

某些编译器是否允许您不这样做就离开?我不记得曾经在源文件中将另一个声明放在类外,我也从未得到任何错误(在MSVC++中)。@Seth Carnegie:这取决于是否“使用”该值。有趣的是,今天早些时候,这件事让我感到不安。代码
struct test{static const int x=10;};无效foo(int const&x){std::cout…要绑定引用,您需要一个左值,这意味着静态成员是根据标准使用的,而使用它的事实意味着需要定义。如果您想一想,引用的绑定需要成员的位置,而该位置需要定义。在右值情况下不需要地址,只需要值,编译器可以将常量插入到位(即,在上面的示例中,编译器将用
10
替换
test::x
)@Seth Carnegie:试着输出一个静态常量变量的地址,msvc也会抱怨。某些编译器会让你不这样做就逃之夭夭吗?我不记得曾经在源文件的类外放过另一个声明,而且我从来没有得到任何错误(在msvc++)。@Seth Carnegie:这一切都取决于你是否“使用”值与否。有趣的是,今天早些时候我就知道了。代码
struct test{static const int x=10;};void foo(int const&x){std::cout…要绑定引用,您需要一个左值,这意味着静态成员是根据标准使用的,而使用它的事实意味着需要定义。如果您想一想,引用的绑定需要成员的位置,而该位置需要定义。在右值情况下不需要地址,只需要值,编译器可以将常量插入到位(即,在上面的示例中,编译器将用
10
替换
test::x
)@Seth Carnegie:试着输出一个静态常量变量的地址,msvc也会抱怨。类主体中的明显定义不是正式的定义,它只是一个声明。它可以使用值,但不能使用对象。c++98标准在这里(在其ODR中)有问题,关于什么时候“使用”了,但它在c++0x中大部分是固定的。如果需要,则需要在源文件(.cpp)中向前声明静态变量