[英]Why is a string literal being over written here (C++)?
我有一個 class 持有一個指針。 我在這里只包含了骨架代碼。 class 構造函數需要一個字符串。
#include <iostream>
#include <string>
using namespace std;
class slice {
public:
slice(string s):
data_(s.data()),
size_(s.size()) {}
const string toString() {
string res(data_, data_+size_);
return res;
}
private:
const char* data_;
const size_t size_;
};
int main() {
slice a{"foo"};
slice b{"bar"};
cout << a.toString() << endl;
cout << b.toString() << endl;
}
該程序的output為:
$ g++ test.cpp && ./a.out
bar
bar
我期待
foo
bar
這里發生了什么? object a 持有的指針如何被覆蓋?
這里發生了什么? object a 持有的指針如何被覆蓋?
您正在經歷未定義的行為。
slice(string s):
data_(s.data()),
size_(s.size()) {}
這里string s
是輸入字符串的副本,並在構造函數的持續時間內存在。 因此s.data()
在構造函數完成后懸空。
a 和 b 是從臨時字符串對象創建的。 當這些字符串對象在語句結束時被銷毀時,它們會釋放它們的 memory,並且指向字符所在位置的底層 char* 變得無效。 您通常不能使用從這樣的字符串中獲取的 char* 。
std::string
對象在超出 scope 時調用其析構函數std::~string()
。
slice(string s) : data_(s.data()), size_(s.size()) {
// After this function is called, the string goes out of scope and s.data() is deallocated by the destructor.
// Leaving gibberish value inside of 'data_' member
}
之后,當您實際打印該值時, data_
到那時已經被銷毀,然后您對它所做的事情會導致未定義的行為(這意味着輸出字符串時程序的行為可以是任何東西,因此術語undefined )。
因為這個問題已經回答了。 我不妨給出一個合理的解決方案。
解決方案:創建一個臨時保存在 class 中的字符串的副本,並在 class 超出 scope 時將其銷毀:
例子:
class slice {
public:
slice(string s):
size_(s.size()) {
// Dynamically allocate a new string so that it doesn't get deleted when it goes out of scope
data_ = new char[s.size()];
// Copy the data into the newly allocated string
s.copy(data_, s.size());
}
slice(const slice&) = default; // Copy constructor
slice(slice&&) = default; // Move constructor
// Destructor
~slice() {
delete[] data_;
}
const string toString() {
// Now 'data_' retains its value even after the string is destroyed
string res(data_, data_+size_);
return res;
}
private:
char* data_;
const size_t size_;
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.