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

Bul*_*net 21 c++ c++-standard-library language-lawyer

我有一个返回指针和长度的函数,我想调用std::string::assign(pointer, length).clear当长度为零且指针可能为nullptr时,是否必须进行特殊情况(调用)?

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.
Run Code Online (Sandbox Code Playgroud)

那么如果n是零呢?什么是零字符数组,如何指向它?打电话有效吗?

s.assign(nullptr, 0);
Run Code Online (Sandbox Code Playgroud)

还是未定义的行为?

s当大小n为零时,libstdc ++的实现似乎不会取消引用指针,但这几乎不是保证.

eer*_*ika 19

小心翼翼地,a nullptr不符合指向大小数组的要求>=0,因此标准不保证行为(它是UB).

另一方面,如果n为零,则不允许实现取消引用指针,因为指针可能是大小为零的数组,并且解引用这样的指针将具有未定义的行为.此外,没有必要这样做,因为没有任何东西被复制.

上述推理并不意味着可以忽略UB.但是,如果没有理由不允许,s.assign(nullptr, 0)那么最好将标准的措辞改为"如果n大于零,那么s指向......".我不知道有什么理由不允许它,但我也不能保证不存在好理由.

请注意,添加支票并不复杂:

s.assign(ptr ? ptr : "", n);
Run Code Online (Sandbox Code Playgroud)

什么是零字符数组

这是:new char[0].自动或静态存储阵列的大小可能不为零.

  • 允许实现检查指针的有效性.检查指针是否指向已分配的内存甚至是简单的检查`__debug_assert(cstr!= nullptr)`可以存在于任何符合要求的实现中 (6认同)

Nic*_*las 12

好吧,你指出,标准说" s指向阵列......".空指针不指向任意数量元素的数组.甚至不是0个元素.另外,请注意s指向" 至少 n元素的数组......".所以很明显,如果n为零,您仍然可以将合法指针传递给数组.

总体而言,std::stringAPI的空指针没有得到很好的保护charT.所以你应该总是确保你交给它的指针是非空的.


Gal*_*lik 9

我不确定为什么实现会取消引用任何指向长度为零的数组的指针.

也就是说,我会谨慎行事.你可能会说你不符合标准要求:

21.4.6.3 basic_string :: assign

8要求:s指向至少n个charT元素的数组

因为nullptr没有指向一个数组.

从技术上讲,行为是不确定的.


eri*_*rip 5

从标准(2.14.7)[lex.nullptr]:

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

std::nullptr_t可以根据4.10.1 [conv.ptr]隐式转换为任何类型的空指针.无论空指针的类型如何,事实仍然是它指向任何东西.

因此,它不满足s指向charT的至少n个元素的数组的要求.

这似乎是未定义的行为.

有趣的是,根据这个答案,C++ 11标准明确指出,它s必须不是basic_string构造函数中的空指针,但此后的措辞已被删除.

  • True但nullptr_t可以隐式转换为任何类型的空指针,包括char*.问题是结果空指针没有指向任何东西,甚至没有指向0个字符,但类型不是问题. (2认同)