C++无法将pair中的指针初始化为NULL。

7

我正在使用 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

有什么不同之处?


5
使用nullptr代替NULL可以吗? - Eric Finn
这不被g++ 4.4支持,只有在4.6版本之后才支持。 - Chap
1个回答

15

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

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*,因此无法调用构造函数。

对于另一种情况,涉及到结构体映射,没有参数推导,赋值语句右边的值必须能够转换为结构体类型,在这种情况下,使用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类型。 - Keith Thompson
nullptr 直到 g++ 4.6 才被添加,但将 NULL 强制转换后可以正确编译。 - Chap
自己实现 nullptr 也是可以的 -- 不要叫它 nullptr,但你可以在不花费太多代价的情况下获得大部分好处。 - Yakk - Adam Nevraumont
@KeithThompson,我说过“NULL被定义为00L或类似的东西”。我认为显而易见的是,在所有情况下它都不会被推断为long,但我会澄清这一点。显然对于GCC来说,它被推断为long,但标准并不要求如此。 - Jonathan Wakely
你的回答似乎暗示了 0 会被解析为 long,但是你最近的编辑已经修复了这个问题。 - Keith Thompson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接