c++ - 使用未定义的比较函数定义 std::map 编译和链接,这让我感到惊讶

标签 c++ c++11

在 std::map、c++11 中,指定键比较函数的函数(指针)可以作为可选参数提供。在摆弄一些这样做的代码时,我从编译器中得到了一些我没有预料到的结果。我尝试了 g++ 和 clang++。他们都同意,我猜编译器很好,但我很困惑。

如果我声明一个 std::map 类型的对象,其中指定了比较函数模板参数,但实际上并没有定义比较函数,代码仍然可以编译和链接,我看不到任何警告。

我用 -std=c++11 -O0 -Wall -Wextra 编译

#include <map>

typedef std::map<int, int, bool(*)(int, int)> Objs;

int main() {

#if 0
  // Compiles and links as expected.
  Objs objs{[](int a, int b) {
    return a < b;
  }};
#endif

#if 1
  // FIXME The lambda definition for the key-comparing function is
  // missing; why does this compile and link?
  Objs objs;
#endif

  objs.emplace(99997, 4210124);
  (void)objs;
  return 0;
}

最佳答案

将单个元素插入到 map 中不需要使用比较器(它是一个元素,应该与什么进行比较?)。

添加第二个将进入UB领域。

(从形式上讲,我认为即使添加一个元素也已经是 UB,因为标准没有明确指定调用比较器函数的时间和次数:在单个元素的情况下不调用似乎非常合理,但调用它只是为了有趣的是传递相同的元素两次我认为不违反 C++ 规则)。

当然请注意,即使进入 UB 并不意味着崩溃......UB 就是 UB 并且任何事情都不会发生(不幸的是,包括什么都没有)。

关于c++ - 使用未定义的比较函数定义 std::map 编译和链接,这让我感到惊讶,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27788162/

相关文章:

c++ - 未计算上下文中的 lambda (C++20 前)

c++ - std::pair 提示类型不完整

c++ - 在 C++ 中创建具有随机枚举类型的 Card 对象

c++ - 获取错误无法从C++ 17编译器的间接库继承构造函数

c++ - 这条线想做什么?

c++ - 转换运算符 template<typename T> T&&() 是否有意转换为右值?

c++ - 类模板链接器错误

c++ - 如何使用 WINE 在 Linux 上使用 Windows .lib

visual-studio - constexpr 无法使用 Visual C++ 编译器 2013 年 11 月 CTP (CTP_Nov2013)

c++ - 如何在不发生冲突的情况下快速散列非常大的子串?