问题
same code, compile with O0, it will report an error:
//============================================================================
// Name : test.cpp
// Author :
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <iostream>
#include <stdint.h>
using namespace std;
class foo{
static const int64_t MAX_THREAD_NUM = 10 * 1000;
public:
void test();
};
void foo::test(){
int64_t a = 100;
// int64_t tmp = MAX_THREAD_NUM;
// int64_t min = std::min(tmp, a);
int64_t min = std::min(MAX_THREAD_NUM, a);
cout << min << endl; // prints !!!Hello World!!!
}
int main() {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
return 0;
}
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/test.d" -MT"src/test.o" -o "src/test.o" "../src/test.cpp"
g++ -o "test" ./src/test.o
./src/test.o: In function `foo::test()':
/home/foo/eclipse-workspace/test/Debug/../src/test.cpp:27: undefined reference to `foo::MAX_THREAD_NUM'
collect2: error: ld returned 1 exit status
/home/foo/eclipse-workspace/test/Debug/../src/test.cpp:27: undefined reference to `foo::MAX_THREAD_NUM'
but with O2 flag, it can compile succeed.
g++ -O2 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/test.d" -MT"src/test.o" -o "src/test.o" "../src/test.cpp"
g++ -o "test" ./src/test.o
g++ version: g++ (Ubuntu 4.8.5-4ubuntu8) 4.8.5 Copyright (C) 2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
回答1:
Program is ill-formed no diagnostic required (NDR) as you break One Definition Rule (ODR) by not providing definition of ODR-used symbol (std::min
takes its argument by reference).
The optimizer removes that unused code and lets you think it is correct.
回答2:
As pointed out by @dfri, compiler inlines MAX_THREAD_NUM
. If we change it to inline static const int64_t MAX_THREAD_NUM = 10 * 1000;
, it will compile fine on O0
. Otherwise, declare but define the variable outside of the class, or mark it constexpr
instead of const
. Using a static const integral member needs definition if it's used where a non-const integral is needed.
class foo {
static const int64_t MAX_THREAD_NUM;
...
};
const int64_t foo::MAX_THREAD_NUM = 10 * 1000;
来源:https://stackoverflow.com/questions/63575194/why-does-c-stdmin-cant-use-a-static-field-as-its-parameter-when-compile-on