为什么g ++在通过const引用将未初始化的值传递给函数时不报告警告?

tem*_*def 3 c++ initialization g++ compiler-warnings

我正在查看前面这个问题中给出的代码,其中包含的代码基本上如下:

bool (*uninitializedFunctionPointer)(int, int);
typedef std::multimap<int, std::string, bool(*)(int, int)> MultiMapType;
MultiMapType myMap(uninitializedFunctionPointer);
Run Code Online (Sandbox Code Playgroud)

请注意(顾名思义)uninitializedFunctionPointer是一个未经过启发的函数指针,它被传递给了构造函数myMap.奇怪的是,当我用g ++ 4.8.4 -Wall -Werror编译这段代码时,它编译了这段代码而没有报告任何警告.但是,它确实报告了此类似代码的错误:

bool (*uninitializedFunctionPointer)(int, int);
uninitializedFunctionPointer(137, 42);
Run Code Online (Sandbox Code Playgroud)

由于调用函数指针触发了警告但是将其传递给multimap构造函数没有,我认为g ++并不关心将未初始化的值作为参数传递给函数.但是,此代码确实会触发警告:

void doSomething(bool (*function)(int, int)) {
    function(137, 42); // Problem if 'function' is uninitialized
}

bool (*uninitializedFunctionPointer)(int, int);
doSomething(uninitializedFunctionPointer); // Warning!
Run Code Online (Sandbox Code Playgroud)

我去了cppreference文档multimap,看到multimap构造函数通过const引用接受它的比较器,所以我尝试编写这段代码:

typedef bool (*FunctionType)(int, int);
void doSomething(const FunctionType &function) {
    function(137, 42); // Problem if 'function' is uninitialized
}

bool (*uninitializedFunctionPointer)(int, int);
doSomething(uninitializedFunctionPointer);
Run Code Online (Sandbox Code Playgroud)

而且,令人惊讶的是,这段代码完全没有任何警告就可以完全编译.我认为这可能与函数指针有关,但看起来并非如此!这里是使用普通旧整数的相关代码:

void doSomething(const int &value) {
    std::cout << value << std::endl; // Problem if value is uninitialized
}

int uninitializedInt;
doSomething(uninitializedInt);
Run Code Online (Sandbox Code Playgroud)

即使已-Wall启用,此代码也会编译完全没有警告.

我知道编译器不需要为各种编程错误发出警告,但g ++会检测到直接使用未初始化的变量并试图通过值将未初始化的变量传递给函数似乎非常不寻常,但是通过const引用将未初始化的变量传递给函数时,不会报告问题.

有没有令人信服的理由为什么g ++不会在这里报告警告?在中,是否存在合理的代码,其中未初始化的变量可以通过const引用传递给函数而不会触发某种未定义的行为?或者这仅仅是编译器的疏忽?

Pet*_*ter 5

问题来自于,在给定引用的情况下,函数可以存储指针或引用.

typedef bool (*FunctionType)(int, int);

FunctionType *stored_function;

void doSomething(const FunctionType &function)
{
     stored_function = const_cast<FunctionType *>(&function);
}

void doSomethingElse(int a, int b)
{
     (*stored_function)(a, b);
}

bool a_function(int, int)
{
    // do something
    return false;
}


int main()
{
    FunctionType func;
    doSomething(func);

    func = a_function;

    doSomethingElse(1,2);
}
Run Code Online (Sandbox Code Playgroud)

这将导致doSomethingElse()调用a_function(),无论分配func是在调用之前还是之后发生doSomething().如果函数定义在不同的编译单元中,并且编译器警告这些事情,那么像上面这样的代码在某些情况下会给出虚假警告.

存在类似的技术,涉及将引用或指针存储为返回对象的成员的函数,该函数稍后将由调用者使用.如果这样的对象的构造函数使用传递的引用初始化const引用或指针,那么const_cast我在这里使用的不是必需的.

对于开发人员来说使用这种技术是一个好主意是另一个故事 - 我当然认为上面的技术很差.但是使用这种技术的开发人员倾向于在他们关于"虚假"警​​告的抱怨中发声 - 包括在一些商业图书馆中 - 因此编译器供应商不愿发出警告.