簡體   English   中英

標准是否保證string :: erase和string :: pop_back不重新分配內存?

[英]Does the standard guarantee that string::erase and string::pop_back DO NOT reallocate memory?

標准是否保證string::erasestring::pop_back 重新分配內存? 擦除一些元素后, string可能會自動收縮嗎?

我檢查了標准,它說string::erasestring::pop_back要么拋出std::out_of_range string::pop_back要么什么都不扔。 我可以將其作為這些方法進行任何重新分配的保證嗎? 由於重新分配可能會拋出bad_alloc

不,合理的實現可能不會重新分配,但標准並不保證這些方法調用不會重新分配,標准說明要求:

引用basic_string序列元素的引用,指針和迭代器可能會被該basic_string對象的以下用法無效:

(4.1)作為任何標准庫函數的參數,將非const basic_string作為參數引用.227

(4.2) 調用非const成員函數,除了operator [],at,data,front,back,begin,rbegin,end和rend

兩種提議的方法屬於類別2,因此兩者都可能改變capacity() ,這隱含地意味着重新分配。

pop_back需要具有與erase相同的效果,因為erase指定為:

效果:確定要刪除的字符串的有效長度xlen,作為nsize() - pos較小的一個。 3

然后該函數將由*this控制的字符串替換為長度為size() - xlen的字符串size() - xlen其第一個pos元素是由*this控制的原始字符串的初始元素的副本,其余元素是元素的副本由*this開始在pos + xlen位置控制的原始字符串。

無法保證如何制作副本,因此可以進行額外的分配或重新分配。


至於

我可以將其作為這些方法不進行任何重新分配的保證嗎? 由於重新分配可能會拋出bad_alloc

該標准似乎沒有明確提到任何方法導致bad_alloc的可能性。 即使有綁定reserve呼叫,也沒有提到它:

void reserve(size_type res_arg=0);

拋出: length_error如果res_arg > max_size()

因此,我認為不能做出這樣的假設。

是的,您可以假設拋出:對這些函數禁止重新分配(可能會拋出bad_alloc )。

20.5.5.12異常處理的限制[res.on.exception.handling]

C ++標准庫中定義的任何函數都可以通過拋出其Throws:段落中描述的類型的異常來報告失敗,或者通過拋出:由異常處理程序捕獲的段落中指定的類型派生的類型來報告失敗對於基本類型。

...

在C ++標准庫中定義的函數沒有拋出:段落但確實有可能拋出的異常規范可能拋出實現定義的異常。 186實現應通過拋出標准異常類的異常或派生出來來報告錯誤(21.6.3.1,21.8,22.2)。

請注意,規范沒有明確說出標有“ 投擲:沒什么”的東西。 不能扔東西。 但在某些時候,常識必須接管。 該標准也沒有明確聲明這些功能無法重新格式化您的磁盤。 通常,標准指定了函數可以執行的操作,並且不允許它們執行任何其他操作。

函數拋出未在Throws: spec(或派生類型)中列出的異常的唯一方法是客戶端以調用未定義行為的方式使用它。

閱讀文檔 ,我認為這取決於函數的簽名。 basic_string& erase(size_type pos = 0, size_type n = npos); 它被描述為前一個字符串的副本 iterator erase(const_iterator first, const_iterator last);的情況下iterator erase(const_iterator first, const_iterator last); 元素被刪除

實際上我對這種差異感到非常驚訝。 我想你不能確定沒有分配。

編輯請注意,在這個小例子中,我在每次檢查時都保留相同的地址:

#include <iostream>
int main()
{
    std::string a;
    for(std::size_t i = 0; i < 10000; ++i)
        a += "Hello World ! My name is Bond... James Bond.";
    std::cout << (long)&a[0] << std::endl;
    a.erase(400000);
    std::cout << (long)&(a[0]) << std::endl;
    a.erase(10);
    std::cout << (long)&(a[0]) << std::endl;
    return 0;
}

我認為它是有保證的,即使標准沒有明確說明。 這是關於重新分配shrink_to_fit的影響的描述:

備注:重新分配使引用序列中的元素以及過去的迭代器的所有引用,指針和迭代器無效。 如果沒有重新分配,它們仍然有效。

如果重新分配發生,所有迭代器,指針,引用都將失效。 但是erasepop_back沒有提到這一點; 這意味着它們不會導致所有這些都失效,然后重新分配就不會發生。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM