【问题标题】:C++ can't initialize a pointer in a pair to NULLC++ 无法将一对中的指针初始化为 NULL
【发布时间】:2013-08-13 19:10:16
【问题描述】:

我正在使用 g++ 4.4.7 进行编译(目前不能更高),并使用 -std=gnu++0x 编译器开关,它应该允许第三行的语法。

typedef std::vector<CI_RecordInfo_Pair>   CI_RecordInfo_Vector;
typedef std::vector<std::pair<std::string, CI_RecordInfo_Vector*> > MgrBlks;
MgrBlks mgr_n_blks { {"T2M_NAME", NULL} };  // <--- line 59

但是,编译器报错如下:

/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_pair.h: In constructor 'std::pair<_T1, _T2>::pair(_U1&&, _U2&&) [with _U1 = const char (&)[9], _U2 = long int, _T1 = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _T2 = CI_RecordInfo_Vector*]':
tom.cpp:59:   instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_pair.h:90: error: invalid conversion from 'long int' to 'CI_RecordInfo_Vector*'

我假设“long int”是 NULL,并且由于某种原因我无法将它转换为指针。然而,在结构图的其他地方,我能够编译类似

foo["X"] = { NULL, "bar", 12 }; // first element is a pointer

有什么区别?

【问题讨论】:

  • 使用nullptr 代替NULL 有效吗?
  • g++ 4.4 不支持。直到 4.6。

标签: c++ pointers null std-pair


【解决方案1】:

编译器拒绝这一行是正确的:

MgrBlks mgr_n_blks { {"T2M_NAME", NULL} };

在 C++11 中 std::pair 有一个模板构造函数,它接受任何参数类型,然后将它们转换为成员:

template<typename X, typename Y>
  pair(X&& x, Y&& y)
  : first(std::forward<X>(x)), second(std::forward<Y>(y))
  { }

NULL 必须定义为00L 或类似的东西,因此模板参数推导将构造函数的模板参数推导出为const char* 和(使用GCC)long。第一个参数类型可转换为std::string,但long不可转换为CI_RecordInfo_Vector*,因此无法调用构造函数。

对于结构映射没有参数推导的另一种情况,赋值的 RHS 必须可转换为结构类型,在这种情况下,NULL 用于直接初始化结构的第一个成员,而不是首先推导出为long,并初始化long,不能转换为指针。

不要在 C++11 中使用NULLnullptr 就是为了避免这些问题而发明的,你应该使用它。

一种可能的解决方法是将参数转换为正确的类型:

MgrBlks mgr_n_blks { {"T2M_NAME", (CI_RecordInfo_Vector*)NULL} };

但使用nullptr 更简单明了。

【讨论】:

  • 如果NULL 被定义为0,那么它的类型是int,而不是long。显然,实现将NULL 定义为0L 或类似的东西。在 g++ 4.7.2 中,NULL 扩展为 __null,显然是 long 类型。
  • nullptr 直到 g++ 4.6 才添加,但转换 NULL 编译正确。
  • @Chap roll-your-own nullptr 也可以——不要叫它nullptr,但你可以不花太多钱就得到大部分好处。
  • @KeithThompson,我说 "NULL 被定义为 00L 或类似的"。我认为很明显它不会在所有情况下都被推断为long,但我会澄清一下。显然对于 GCC,它被推断为 long,但这不是标准要求的。
  • 您的回答似乎暗示0 将解析为long;你最近的编辑修复了这个问题。
猜你喜欢
  • 1970-01-01
  • 2017-09-06
  • 2018-09-02
  • 1970-01-01
  • 2013-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多