[英]c++ std::string changed unexpected. I think this problem is about deep & shallow copy
我創建了簡單的C ++ std::string
值。
但是該值會產生意想不到的結果。
我使用g ++編譯器(Linux)和Visual Studio(Windows)測試了此代碼,並且兩個編譯器都出現相同的問題。
正常結果代碼
/* This code results are Normal */
#include <bits/stdc++.h>
int main() {
std::string a1 = "a1";
std::string a2 = "a2";
std::string b1("b1");
std::string b2("b2");
const char *c1 = std::string("c1").c_str();
const char *c2 = std::string("c2").c_str();
std::cout << "Expected [a1], real [" << a1 << "]\n";
std::cout << "Expected [a2], real [" << a2 << "]\n";
std::cout << "Expected [b1], real [" << b1 << "]\n";
std::cout << "Expected [b2], real [" << b2 << "]\n";
std::cout << "Expected [c1], real [" << c1 << "]\n";
std::cout << "Expected [c2], real [" << c2 << "]\n";
}
控制台結果:
Expected [a1], real [a1]
Expected [a2], real [a2]
Expected [b1], real [b1]
Expected [b2], real [b2]
Expected [c1], real [c1]
Expected [c2], real [c2]
結果代碼異常
/* This code results has some problem. */
#include <bits/stdc++.h>
int main() {
const char *c1 = std::string("c1").c_str();
const char *c2 = std::string("c2").c_str();
std::string a1 = "a1";
std::string a2 = "a2";
std::string b1("b1");
std::string b2("b2");
// const char *c1 = std::string("c1").c_str();
// const char *c2 = std::string("c2").c_str();
std::cout << "Expected [a1], real [" << a1 << "]\n";
std::cout << "Expected [a2], real [" << a2 << "]\n";
std::cout << "Expected [b1], real [" << b1 << "]\n";
std::cout << "Expected [b2], real [" << b2 << "]\n";
std::cout << "Expected [c1], real [" << c1 << "]\n"; // c1 = b2?
std::cout << "Expected [c2], real [" << c2 << "]\n"; // b2 = b2?
}
控制台結果:
Expected [a1], real [a1]
Expected [a2], real [a2]
Expected [b1], real [b1]
Expected [b2], real [b2]
Expected [c1], real [b2]
Expected [c2], real [b2]
我通常只使用string str = ""
,但是我想知道何時進行測試。
我認為構造函數應該有一個問題。
我如何理解std :: string的異常結果?
問題就在這里
const char *c1 = std::string("c1").c_str();
const char *c2 = std::string("c2").c_str();
您在這里所做的是,在每一行中,創建一個臨時的std::string
對象,獲取一個指向其內容的指針,並將該指針分配給變量。 在每一行的末尾,臨時的std::string
將被破壞,並且您通過.c_str()
獲得的指針將變成懸空的指針 ……
通常,兩個版本的代碼都具有未定義的行為 。 這僅意味着:您編寫的代碼違反了允許編譯器進行工作的基本假設(例如,如果您決定取消引用指針,則該指針實際上指向有效對象),因此,編譯器不能期望以某種方式神奇地產生一個有意義的程序。 關於第一個版本為何“起作用”(即似乎起作用)而第二個版本與編譯器將C ++代碼轉換成何種機器代碼無關的確切解釋。 通常,請注意,在第二個版本中,您的兩個臨時字符串是要構造的第一個字符串。 一旦這些臨時字符串被銷毀,為它們分配的任何內存都可以用於以后創建的字符串。 另一方面,在第一個示例中,臨時字符串是要構造的最后一個字符串。 臨時字符串銷毀后,將不再構造需要內存的其他本地對象。 因此,您的兩個指針所指向的內存內容不會被覆蓋的可能性很小。 因此,盡管您的指針將不再是有效的指針,並且將不允許訪問它們指向的對象(因為這些對象不再存在),但是無論如何這樣做仍然可能會產生預期的結果。
由於您沒有說明使用的確切編譯器版本和編譯選項,因此很難確切說明您的編譯器在做什么。 但是,讓我們看一下最新的GCC在優化級別-O2
會做什么(我無法僅使用默認設置來重現該問題)。 當前GCC版本使用的標准庫默認情況下執行短字符串優化 。 每個有問題的字符串只有兩個字符長。 因此, std::string
對象的內部緩沖區和.c_str()
結果實際上將位於堆棧上的std::string
對象內部。 查看上面代碼的第一個和第二個版本的程序集,我們看到編譯器確實確實將臨時字符串放在第一個版本的堆棧中的兩個單獨位置,而將它們放置在以后的同一位置。在第二個版本中構造字符串b2
…
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.