首页 > string被不断赋值的具体实现

string被不断赋值的具体实现

c++中,string是一个管理者,比如创建出一个string的对象后,这个对象是管理一个地方里面保存有字符串的,那么,创立了一个string后对象并初始化后,还能对它再赋值吗?如果再赋值是什么含义呢,是这个地方的字符串变换了吗(但是地址没有变),还是这一块地址里面依然有原来的字符串而这个string对象管理了另外一块地址的另外一个字符串呢?
比如说以下代码假设state.txt中是New York#New Mexico#Texas#Indiana
那么string city 就不断被赋值各个城市名称,这里面具体是如何实现的?

#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main(){
    ifstream input("state.txt");
    if(input.fail())
    {
        cout<<"File does not exist"<<endl;
        cout<<"Exit program"<<endl;
        return 0; 
    }
    string city;
    while(!input.eof())
    {
        getline(input,city,'#');
        cout<<city<<endl;
    }
    input.close();
    cout << "Done" <<endl;
    return 0; 
}

再赋值当然是可以的,如果之前分配的内存够用就直接在里面写上新内容,如果不够就重新分一块。
就酱。


string类中维护了三个指针:

using _Base::_M_start; 
using _Base::_M_finish;
using _Base::_M_end_of_storage;

_M_start为保存字符串的起始地址;_M_finish为终止地址;
_M_end_of_storage为string对象中当前申请空间的大小;
在第一次赋值后,_M_finish和_M_end_of_storage是一样大的(也可能不一样大,有的实现中考虑到对齐,一次可能会多分配几个字节)
在后续再赋值时:
1)如果新值的长度小于当前字符串的长度,使用memcpy直接拷贝;地址空间不变;
2)如果新值的长度大于当前当前字符串的长度,会申请一个新的空间,将新值拷贝过去,并释放原有空间;

string的c_str()方法返回的就是_M_start的值,将这个值打出来就知道地址是否变化:
写了一个示例,查看string的几个函数的返回值:

// comparing size, length, capacity and max_size
#include <iostream>
#include <string>

int main ()
{
  std::string str ("Test string");
  std::cout << "size: " << str.size() << "\n";
  std::cout << "length: " << str.length() << "\n";
  std::cout << "capacity: " << str.capacity() << "\n";
  std::cout << "max_size: " << str.max_size() << "\n";

  std::cout << "befor change:" << str  << "/size:" << str.size() << "/capacity:" << str.capacity() << "/addr:" << long(str.c_str()) << std::endl;
  str = "hello,coli";
  std::cout << "after change:"  << str  << "/size:" << str.size() << "/capacity:" << str.capacity() << "/addr:" << long(str.c_str()) << std::endl;
  str = "hello,colin,wo";
  std::cout << "after change:"  << str  << "/size:" << str.size() << "/capacity:" << str.capacity() << "/addr:" << long(str.c_str()) << std::endl;
  str = "llllllllllllllllllllllllllllllllllllllllllll";
  std::cout << "long change:"  << str  << "/size:" << str.size() << "/capacity:" << str.capacity() << "/addr:" << long(str.c_str()) << std::endl;
  str = "aa";
  std::cout << "short change:"  << str  << "/size:" << str.size() << "/capacity:" << str.capacity() << "/addr:" << long(str.c_str()) << std::endl;
  return 0;
}

output:
size: 11
length: 11
capacity: 11
max_size: 1073741820
befor change:Test string/size:11/capacity:11/addr:8990612
//新值小于旧值,使用原有空间,地址不变
after change:hello,coli/size:10/capacity:11/addr:8990612
//新值大于旧值,申请新空间
after change:hello,colin,wo/size:14/capacity:14/addr:8990644
long change:llllllllllllllllllllllllllllllllllllllllllll/size:44/capacity:44/add
r:8982500
short change:aa/size:2/capacity:44/addr:8982500

附上部分string源码:

size_type capacity() const { return (_M_end_of_storage - _M_start) - 1; }
const _CharT* c_str() const { return _M_start; }

basic_string& operator=(const basic_string& __s) {
    if (&__s != this) 
      assign(__s.begin(), __s.end());
    return *this;
  }

参考:SGI STL的string的实现:
http://www.sgi.com/tech/stl/string

【热门文章】
【热门文章】