`string.assign(string.data(), 5)` 是定义明确的还是 UB?

Quu*_*one 11 c++ stl undefined-behavior

一个同事想写这个:

std::string_view strip_whitespace(std::string_view sv);

std::string line = "hello  ";
line = strip_whitespace(line);
Run Code Online (Sandbox Code Playgroud)

我说返回string_view让我先验地感到不安,而且,这里的别名对我来说看起来像 UB。

我可以肯定地说,line = strip_whitespace(line)在这种情况下相当于line = std::string_view(line.data(), 5). 我相信会调用string::operator=(const T&) [with T=string_view],其定义为等价于line.assign(const T&) [with T=string_view],其定义为等价于line.assign(line.data(), 5),其定义为:

Preconditions: [s, s + n) is a valid range.
Effects: Replaces the string controlled by *this with a copy of the range [s, s + n).
Returns: *this.
Run Code Online (Sandbox Code Playgroud)

但这并没有说明出现混叠时会发生什么。

我昨天在 cpplang Slack 上问了这个问题,得到的答案喜忧参半。在这里寻找超级权威的答案,和/或对真实图书馆供应商实施的实证分析。


我写测试用例string::assignvector::assigndeque::assignlist::assign,和forward_list::assign

  • Libc++ 使所有这些测试用例都能工作。
  • Libstdc++ 使它们都能正常工作,除了forward_list, 段错误。
  • 我不知道 MSVC 的库。

libstdc++ 中的段错误让我希望这是 UB;但我也看到 libc++ 和 libstdc++ 都在努力使这项工作至少在常见情况下有效。

eca*_*mur 8

除非有几个例外,其中您不是一个例外,否则assign在字符串上调用非常量成员函数(即)会使[...] 指向其元素的指针 [...]无效。这违反了先决条件assign[s, s + n)是一个有效的范围内,所以这是不确定的行为。

请注意,它string::operator=(string const&)具有专门使自分配成为空操作的语言。

  • @Fuleeish我也不知道,但请参阅[LWG问题526](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-close.html#526),关闭为“ *不是缺陷*”,它在闭包建议中提到,如果“value”位于向量本身中,“std::vector::insert(iterator pos, const T& value)”必须起作用,因为标准不这样做指定允许它不工作,即使该引用可能会因调用而失效。 (2认同)