尝试理解字符串对象

时间:2015-06-08 15:36:33

标签: c++ string

运行一个简单的程序来测试字符串对象中的指针,得到

0x1875028
Hello 
0x1875058 0x1875028
Hello world!!!
0x1875028

我想了解为什么s.c_str()会在erase()调用之后更改值,而不是st.c_str()

以下是简单的代码:

#include <vector>
#include <unordered_map>
#include <iostream>
#include <stdlib.h>
#include <string>

using namespace std;

string st;
void dum() {
    string s("Hello world!!!");
    printf("%p\n", s.c_str());
    st = s;
    s.erase(6);
    cout << s << endl;
    printf("%p %p\n", s.c_str(), st.c_str());
}


int main(int argc,char *argv[]) {
    dum();
    cout << st << endl;
    st.erase(6);
    printf("%p\n", st.c_str());
    return 0;
}

2 个答案:

答案 0 :(得分:1)

这实际上取决于您使用的版本。例如,请参阅Is std::string refcounted in GCC 4.x / C++11?。当你写两个stringab

a = b;

然后有一个问题是它们是否在内部指向同一个对象(直到其中一个被修改)。因此,您的计划展示的任何一种行为都不是很令人惊讶。

答案 1 :(得分:0)

首先,我认为这属于实施细节伞。

我用VS2013试过了。

调用c_str()后,s返回的字符串指针不会更改,因为我认为内部字符串实现只是更新字符串的结尾(更改一些内部数据成员),而不是内部字符串缓冲区的新堆重新分配(这样的操作可能会返回一个新的指针值)。

我注意到这是一种针对您的本地st字符串和全局st = s字符串的行为。

请注意,VS2013附带的STL实现不使用COW(COW似乎是非标准的C ++ 11兼容),因此当您使用#include <iostream> #include <string> using namespace std; // Helper function to print string's c_str() pointer using cout inline const void * StringPtr(const string& str) { // We need a const void* to make cout print a pointer value; // since const char* is interpreted as string. // // See for example: // How to simulate printf's %p format when using std::cout? // http://stackoverflow.com/q/5657123/1629821 // return static_cast<const void *>(str.c_str()); } string st; void f() { string s{"Hello world!!!"}; cout << "s.c_str() = " << StringPtr(s) << '\n'; st = s; s.erase(6); cout << s << '\n'; cout << "s.c_str() = " << StringPtr(s) << "; st.c_str() = " << StringPtr(st) << '\n'; } int main() { f(); cout << st << endl; st.erase(6); cout << "st.c_str() = " << StringPtr(st) << '\n'; } 复制字符串时,您正在执行< em> deep copy ,因此这两个字符串是完全独立的,它们指向存储各自字符串内容的不同内存缓冲区。因此,当您从一个字符串中删除某些内容时,此操作绝不会反映到另一个复制的字符串中。

示例代码

C:\Temp\CppTests>cl /EHsc /W4 /nologo test.cpp
test.cpp

C:\Temp\CppTests>test.exe
s.c_str() = 0036FE18
Hello
s.c_str() = 0036FE18; st.c_str() = 01009A40
Hello world!!!
st.c_str() = 01009A40

<强>输出

os.system