簡體   English   中英

cplusplus.com說std :: string的過去結尾“不能被解除引用”

[英]cplusplus.com says that the past-the-end of an std::string “shall not be dereferenced”

如果你能為我清除一些困惑,我想要它。 我正在編寫一個函數來刪除字符串中的重復字符,例如“AB - >”AAABB“。

void remove_dups(std::string& str) { 
    std::string::iterator it = str.begin();
    while (it != str.end()) {
        if (*(it+1) == *it) {
            str.erase(it+1);
        } else {
            ++it;
        }
    }
} 

它在測試時似乎有效。 但是,我想知道,不應該有柵欄問題嗎? 當'it'是字符串的結尾時,if語句會查看不存在的下一個字符。 根據cplusplus.com,

過去的結尾字符是一個理論字符,它將跟隨字符串中的最后一個字符。 它不應被解除引用。 http://www.cplusplus.com/reference/string/string/end/

所以我想知道為什么我的函數似乎通過了測試,以及如何以優雅的方式重寫整個事情來繞過fencepost問題。 (對我來說很容易,伙計。我是一個n00b。)

像它一樣重寫它

void remove_dups(std::string& str) { 
    std::string::iterator it = str.begin();
    while (it != str.end()) {
        if ((it+1) != str.end() && *(it+1) == *it) {
            str.erase(it+1);
        } else {
            ++it;
        }
    }
} 

似乎不優雅。

所以我想知道為什么我的函數似乎通過了測試

未定義的行為並不意味着它不會做你想要的。 它可能完全符合您的要求,只是出於錯誤的原因。 我猜測未定義的行為表現為獲取\\0字符,它不可能與字符串中的其他字符進行比較。

以及如何以優雅的方式重寫整個事物來繞過fencepost問題

有很多選擇,但我個人的偏好是這樣的

if (it != str.end()) {
  ++it;
  while (it != str.end()) {
    /* compare *it and *(it-1) */
  }
}

但要注意erase必須移動元素。 假設您總共刪除了20個字符。 你將字符串的其余部分移回一個字符20次。 如果您稍微修改算法,則不需要這樣做:

void remove_dups(std::string& str) { 
  std::string::iterator src = str.begin();
  std::string::iterator dst = str.begin();
  if (src != str.end()) {
    ++src;
    ++dst;
    while (src != str.end()) {
      if (*src != *(src-1)) {
        *dst = *src;
        ++dst;
      }
      ++src;
    }
    str.resize(dst - str.begin());
  }
}

這種方法還有一個好處,即使erase會在內存中移動字符串,這可能會導致迭代器中斷。

標准允許與最后一個數組元素進行比較,不允許取消引用它。 因此,您可以比較其地址,以驗證循環是否應該結束,但不允許您讀取內容。 由於迭代器主要是指針,因此該規則也適用於字符串,向量,...

另外,請注意string :: erase的非序列版本將迭代器返回到占用已刪除元素的字符,您可以將其用作新的循環迭代器。

我認為最干凈的解決方案是停止在字符串的末尾(字符串的最后一個字符),因為在那時,無論如何都不會執行進一步的操作。

因此, while (it != str.end())應該是while (it != str.end() && it != (str.end() - 1))

暫無
暫無

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

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