我有一个返回指针和长度的函数,我想调用std::string::assign(pointer, length)
。当长度为零且指针可能为nullptr时,是否必须创建一个特殊情况(调用clear
)?
C ++标准说:
21.4.6.3 basic_string::assign
basic_string& assign(const charT* s, size_type n);
Requires: s points to an array of at least n elements of charT.
那么如果n
为零呢?什么是零字符数组,如何指向它?
调用
s.assign(nullptr, 0);
还是未定义的行为?
当大小s
为零时,libstdc ++的实现似乎不会取消引用指针n
,但这几乎不是保证。
答案 0 :(得分:19)
迂腐地说,nullptr
不符合指向大小为>=0
的数组的要求,因此标准不保证行为(它是UB)。
另一方面,如果n
为零,则不允许实现取消引用指针,因为指针可能是大小为零的数组,并且取消引用这样的指针将具有未定义的行为。此外,没有必要这样做,因为没有任何东西被复制。
上述推理并不意味着可以忽略UB。但是,如果没有理由不允许s.assign(nullptr, 0)
,那么最好将标准的措辞改为“如果n大于零,则s指向......”。我不知道有什么理由不允许它,但我也不能保证不存在好理由。
请注意,添加支票并不复杂:
s.assign(ptr ? ptr : "", n);
什么是零字符数组
这是:new char[0]
。自动或静态存储阵列的大小可能不为零。
答案 1 :(得分:12)
当你指出时,标准说“s
指向数组......”。空指针不指向任意数量元素的数组。甚至不是0个元素。另请注意,s
指向“一组至少 n
元素......”。所以很明显,如果n
为零,您仍然可以将合法指针传递给数组。
总的来说,std::string
的API没有得到针对charT
的空指针的良好保护。所以你应该总是确保你交给它的指针是非空的。
答案 2 :(得分:9)
我不确定为什么实现会取消引用任何指向长度为零的数组的指针。
那就是说,我会谨慎行事。你可能会说你没有达到标准要求:
21.4.6.3 basic_string :: assign
8 要求:s指向至少n个charT元素的数组
因为nullptr
未指向数组。
从技术上讲,这种行为是不确定的。
答案 3 :(得分:5)
来自标准(2.14.7)[lex.nullptr]:
根据4.10.1 [conv.ptr],指针文字是关键字nullptr。它是
std::nullptr_t
类型的prvalue。 [注意:std::nullptr_t
是一种不同的类型,既不是指针类型也不是指向成员类型的指针 ...]
std::nullptr_t
可以隐式转换为任何类型的空指针。无论空指针的类型如何,事实仍然是它指向 nothing 。
因此,它不符合 s指向charT 的至少n个元素的数组的要求。
这似乎是未定义的行为。
有趣的是,根据this answer,C ++ 11标准明确指出s
不能是basic_string
构造函数中的空指针,但此后的措辞已被删除。