C++ 之 stl::string 寫時拷貝導致的問題
一、寫時拷貝原理
String是使用計數器來記錄引用計數,當有新的string對象共享內存塊時,計數器+1,當有對象觸發寫時拷貝或析構時,計數器-1。
那么計數器存放在哪里呢?std::string會在堆里分配空間存儲計數器,由第一個創建的對象分配并初始化計數器。stl的實現就是在string內存空間的最前面分配了空間存儲計數器。
二、寫時拷貝容易引發的問題
問題主要出現在直接使用 sprintf 操作 string 的內部指針地址 (char)s.c_str() 。
#include <stdio.h>
#include <iostream>
#include <string>
int main()
{
std::string s1 = "efghijk";
std::string s2 = s1;
std::string s3 = s1;
sprintf((char*)s1.c_str(), "%s", "abcde");
std::cout << "s1=" << s1 << std::endl;
std::cout << "s2=" << s2 << std::endl;
std::cout << "s3=" << s3 << std::endl;
}
輸出結果為(j沒有顯示在string是由于在sprintf時,abcde后面還有一個\0字符):
s1=abcdek
s2=abcdek
s3=abcdek
通過 string::resize() 分配內存空間。 通過 string::c_str() 直接獲取內存空間的起始地址并寫入數據。
這樣會導致s1和s2和s3都發生變化,所以盡量不要使用string的.c_str函數進行賦值操作,不然容易由于copy on right導致的無法直觀想到的錯誤。

浙公網安備 33010602011771號