将nullptr传递给std :: string :: assign是否有效?

时间:2016-01-20 13:51:25

标签: c++ language-lawyer c++-standard-library

我有一个返回指针和长度的函数,我想调用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,但这几乎不是保证。

4 个答案:

答案 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]:

  

指针文字是关键字nullptr。它是std::nullptr_t类型的prvalue。 [注意:std::nullptr_t   是一种不同的类型,既不是指针类型也不是指向成员类型的指针 ...]

根据4.10.1 [conv.ptr],

std::nullptr_t可以隐式转换为任何类型的空指针。无论空指针的类型如何,事实仍然是它指向 nothing

因此,它不符合 s指向charT 的至少n个元素的数组的要求。

这似乎是未定义的行为。

有趣的是,根据this answer,C ++ 11标准明确指出s不能是basic_string构造函数中的空指针,但此后的措辞已被删除。