一位同事想这样写:
std::string_view strip_whitespace(std::string_view sv);
std::string line = "hello ";
line = strip_whitespace(line);
我说过归来string_view
使我先天不安,而且,在我看来,这里的别名看起来像UB。
我可以肯定地说line = strip_whitespace(line)
在这种情况下等于line = std::string_view(line.data(), 5)
。我相信will call 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.
但是,这并不能说明出现别名时会发生什么。
我昨天在cpplang Slack上问了这个问题,并得到了不同的答案。在这里寻找超级权威的答案,和/或对真实库供应商实施的经验分析。
我写测试用例了string::assign
,vector::assign
,deque::assign
,list::assign
,和forward_list::assign
。
- Libc ++使所有这些测试用例都能正常工作。
- Libstdc ++使它们都可以工作
forward_list
,但segfaults 除外。 - 我不知道MSVC的库。
libstdc ++中的段错误使我希望它是UB。但是我也看到libc ++和libstdc ++都将付出巨大的努力,至少在通常情况下才能使此工作正常。
您是否使用ASan编译了测试用例并/或在Valgrind下运行它们?尽管代码仍可能在实践中而不是按定义运行,但这样可以避免猜测是否会导致代码违反访问权限。
—
康拉德·鲁道夫
“如果basic_string的任何成员函数或运算符引发异常,则该函数或运算符对basic_string对象没有其他影响。” -这会强制在分配现有存储空间之前进行存储空间分配,以便在分配失败的情况下抛出异常,而无需更改
—
Sam Varshavchik
*this
。但是我看不出有什么办法可以防止重复使用现有存储,在这种情况下,由于复制存储的语义是不确定的,因此这种情况变得不确定。
—
胡桃