Seorang rekan kerja ingin menulis ini:
std::string_view strip_whitespace(std::string_view sv);
std::string line = "hello ";
line = strip_whitespace(line);
Saya mengatakan bahwa kembali string_view
membuat saya tidak enak a priori , dan lebih jauh, aliasing di sini tampak seperti UB bagi saya.
Saya dapat mengatakan dengan pasti bahwa line = strip_whitespace(line)
dalam hal ini setara dengan line = std::string_view(line.data(), 5)
. Saya percaya bahwa akan memanggil string::operator=(const T&) [with T=string_view]
, yang didefinisikan setara dengan line.assign(const T&) [with T=string_view]
, yang didefinisikan setara dengan line.assign(line.data(), 5)
, yang didefinisikan untuk melakukan ini:
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.
Tapi ini tidak mengatakan apa yang terjadi ketika ada alias.
Saya menanyakan pertanyaan ini di Slack cpplang kemarin dan mendapat jawaban beragam. Mencari jawaban yang super otoritatif di sini, dan / atau analisis empiris implementasi vendor perpustakaan nyata.
Saya menulis uji kasus untuk string::assign
, vector::assign
, deque::assign
, list::assign
, dan forward_list::assign
.
- Libc ++ membuat semua test case ini berfungsi.
- Libstdc ++ membuat semuanya berfungsi kecuali
forward_list
, yang segfaults. - Saya tidak tahu tentang perpustakaan MSVC.
Segfault di libstdc ++ memberi saya harapan bahwa ini adalah UB; tapi saya juga melihat libc ++ dan libstdc ++ akan berusaha keras untuk membuat ini bekerja setidaknya dalam kasus umum.
sumber
*this
. Tapi saya tidak melihat apa pun untuk mencegah penyimpanan yang ada digunakan kembali, dalam hal ini menjadi tidak ditentukan, karena semantik copy-overing penyimpanan tidak ditentukan.std::string::assign
kasing dan kasing (std::vector::assign
khusus) .assign
persyaratan di [tab: container.seq.req] .Jawaban:
Kecuali beberapa pengecualian yang bukan milik Anda, memanggil fungsi anggota non-const (yaitu
assign
) pada string membatalkan [...] pointer [...] ke elemen-elemennya. Ini melanggar prasyarat tentangassign
itu[s, s + n)
adalah rentang yang valid, jadi ini adalah perilaku yang tidak terdefinisi.Perhatikan bahwa
string::operator=(string const&)
memiliki bahasa yang khusus untuk menjadikan penugasan mandiri sebagai larangan.sumber
assign
? Jika ya, maka kita harus menetapkan titik tertentu di dalam penerapan assign to mark ketika tepatnya pembatalan dapat terjadi, dan saya percaya itu bukan sesuatu yang akan dilakukan C ++. Saya bisa saja salah.std::vector::insert(iterator pos, const T& value)
harus bekerja jikavalue
masuk ke dalam vektor itu sendiri, karena standar tidak menentukan bahwa itu diizinkan untuk tidak berfungsi, meskipun referensi itu mungkin dibatalkan oleh panggilan.