为什么 g++ 在通过 const 引用将非初始值传递到函数时不报告警告?
Why doesn't g++ report warnings when passing uninitalized values into functions by const reference?
我正在查看前面的问题中给出的代码,其中包括基本上如下的代码:
bool (*uninitializedFunctionPointer)(int, int);
typedef std::multimap<int, std::string, bool(*)(int, int)> MultiMapType;
MultiMapType myMap(uninitializedFunctionPointer);
请注意,(顾名思义)uninitializedFunctionPointer
是一个传入 myMap
构造函数的未初始化函数指针。奇怪的是,当我使用 g++ 4.8.4 和 -Wall -Werror
编译此代码时,它编译了这段代码而没有报告任何警告。但是,它确实报告了以下类似代码的错误:
bool (*uninitializedFunctionPointer)(int, int);
uninitializedFunctionPointer(137, 42);
由于调用函数指针触发了警告,但将其传递到multimap
构造函数中并没有,因此我认为 g++ 并不关心将未初始化的值作为参数传递给函数。但是,此代码确实会触发警告:
void doSomething(bool (*function)(int, int)) {
function(137, 42); // Problem if 'function' is uninitialized
}
bool (*uninitializedFunctionPointer)(int, int);
doSomething(uninitializedFunctionPointer); // Warning!
我访问了 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);
而且,令人惊讶的是,这段代码完全可以编译,完全没有警告。我认为这可能与函数指针有关,但看起来并非如此!以下是仅使用普通旧整数的相关代码:
void doSomething(const int &value) {
std::cout << value << std::endl; // Problem if value is uninitialized
}
int uninitializedInt;
doSomething(uninitializedInt);
此代码编译时没有任何警告,即使启用了-Wall
也是如此。
我知道编译器不需要对所有类型的编程错误发出警告,但 g++ 会检测到直接使用未初始化的变量并尝试按值将未初始化的变量传递到函数中,但在通过 const 引用将未初始化的变量传递到函数中时不会报告问题。
是否有令人信服的理由说明 g++ 不会在此处报告警告?例如,是否有合理的代码可以通过 const 引用将未初始化的变量传递到函数中而不会触发某种未定义的行为?或者这只是编译器中的疏忽?
问题出现是因为,给定一个引用,函数可以存储指针或引用。
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);
}
这将导致doSomethingElse()
调用a_function()
,无论对func
的赋值发生在doSomething()
调用之前还是之后。 如果函数定义位于不同的编译单元中,并且编译器警告此类内容,则上述代码在某些情况下会给出虚假警告。
有类似的技术涉及将引用或指针存储为返回对象成员的函数,调用方稍后将使用。 如果此类对象的构造函数使用传递的引用初始化 const 引用或指针,则不需要我在此处使用的const_cast
。
开发人员使用这种技术是否是一个好主意是另一回事 - 我当然认为上述技术很差。 但是使用这种技术的开发人员往往会抱怨"虚假"警告 - 包括一些商业库 - 因此编译器供应商宁愿不发出警告。
- 为什么可以将左值传递给"std::async",即使它引用了右值
- 将具有嵌入式单声道的 C++ 函数指针传递给 C#
- 当值传递给C++中的运算符重载函数时会发生什么
- 将函数对象传递给 std::function
- 如何将非可变参数值传递给 fmt::format?
- 将 qml 项目值传递给 cpp 后如何与它们进行交互?
- NDK:将文本字段值传递给 c++ 字符串
- 将函数指针传递给 C++ 中的成员函数.收到错误
- 如何将值传递给 lambda 函数
- 如何在C++中将std::string值传递给RegSetValueEx()
- 如何将函数变量传递给C lambda函数
- 如何将 c ++ 变量的值传递给 hadoop HDFS 的 bash 系统命令?
- C++ 通过参数将值传递给 char 数组
- 如何将 java 函数指针传递给 c++ 本机代码
- 如何将值传递给MFC消息映射函数on_command
- 如何将函数中的多个值传递给C++中的不同函数
- 将多个解析值传递给 addPositionalArgument 函数
- C++为什么将左值传递给move构造函数对模板有效
- 一种自动检测对象的方法,该方法通过值传递给c++中的函数
- 试图将整型转换为void以按值传递给pthread函数