你能为自己分配一个std :: string的子字符串吗?

时间:2015-01-25 21:55:55

标签: c++ string

我最近发现需要用自己的子字符串替换std::string的内容。我认为最合乎需要的函数来自http://www.cplusplus.com/reference/string/string/assign/

  

substring(2) string& assign(const string& str,size_t subpos,size_t sublen);
  
  复制从字符位置subpos开始的str部分并跨越sublen字符(或者直到str的结尾,如果str太短或者如果sublen是string :: npos)。

     

str
  另一个字符串对象,其值可以复制或移动。

     

subpos
  str中第一个字符的位置,作为子字符串复制到对象。如果这大于str的长度,则抛出out_of_range。注意:str中的第一个字符用值0表示(不是1)。

     

sublen
  要复制的子字符串的长度(如果字符串较短,则复制尽可能多的字符)。       string :: npos的值表示直到str结尾的所有字符。

但是,我不确定这是否允许,或者它是否可以破坏字符串数据。我知道memcpy()例如,不允许(或者至少不保证在没有损坏的情况下)用自身的一部分覆盖内存区域(参见memcpy() vs memmove()) 。但我不知道上述方法是否有相同的限制。

更一般地说,如果我能够自己找出这个问题的答案,请你评论一下吗?我链接到的文档中没有任何内容让我清楚地知道这个问题的答案是什么,除了或许 str参数描述中的限定符“Another”(“< em>另一个字符串对象“),这似乎意味着它不能是 this 对象,尽管我没有发现它是明确的。这是文档中的弱点吗?

3 个答案:

答案 0 :(得分:1)

此操作由[string :: assign] / 4:

定义
basic_string& assign(const basic_string& str, size_type pos,
    size_type n = npos);
     

效果:确定要分配的字符串的有效长度rlen   作为nstr.size() - pos中的较小者,并调用assign(str.data() + pos rlen)

dat typo

然后:

basic_string& assign(const charT* s, size_type n);
     

效果:用字符串替换*this控制的字符串   长度n,其元素是s指向的那些元素的副本。

关于这一点,没有任何关于str.assign(str, 0)是否安全的说法(特别是,当每个角色的副本发生时,我们无法知道。)。

因此我强烈建议你不要这样做。

答案 1 :(得分:0)

不要尝试。

它可能会起作用,但是如所选答案中所建议,它不能保证安全。在最佳情况下,根据您的实现,将创建一个临时对象,然后将其销毁。

一种模拟方法,它不会创建临时对象,而且确实比调用assignsubstr更快:

void trimTo(string & s, size_t pos = 0, size_t len = string::npos)
{ 
    s.erase(pos + len); 
    s.erase(pos, len); 
}

然后

trimTo(myString, fromPos, numChars);

用作

myString.assign(myString.substr(fromPos, numChars);

但是至少快两倍。

答案 2 :(得分:0)

显然,这是与operator =(防止自我分配)相同的决定。

_Myt& assign(const _Myt& _Right,
    size_type _Roff, size_type _Count = npos)
    {   // assign _Right [_Roff, _Roff + _Count)
    _Right._Check_offset(_Roff);
    _Count = _Right._Clamp_suffix_size(_Roff, _Count);

    if (this == &_Right)
        erase((size_type)(_Roff + _Count)), erase(0, _Roff);    // substring
    else if (_Grow(_Count))
        {   // make room and assign new stuff
        _Traits::copy(this->_Myptr(),
            _Right._Myptr() + _Roff, _Count);
        _Eos(_Count);
        }
    return (*this);
    }