[英]Using smart pointers in a struct or class
我編寫了一個函數,用於從文件中加載字節並返回包含字節緩沖區和緩沖區長度的FileData結構。
我希望緩沖區一旦被消耗並被拋出范圍就被刪除。
由於各種播放錯誤,我無法編譯它。 此外,我不確定緩沖區是否正確移動而不是復制。 我不介意FileData結構本身被復制,因為它最多可能是16個字節。
一般來說,如何將智能指針用作類/結構域? 這甚至是你做的事情嗎?
我知道這是一個含糊不清的問題,但由於我在智能指針方面存在一些概念上的困難,我希望這個例子能幫助我朝着正確的方向前進。
這是我到目前為止所得到的:
struct FileData
{
unique_ptr<char[]> buf;
unsigned int len;
};
FileData LoadFile(string filename)
{
ifstream str;
str.open(filename, ios::binary);
str.seekg(0, ios::end);
auto len = str.tellg();
str.seekg(0, ios::beg);
char* buf = new char[len];
str.read(buf, len);
str.close();
FileData d = { unique_ptr<char[]>(buf), len };
return d;
}
編輯:由於有些人對我使用當前代碼得到的錯誤消息感到好奇,這里是:
error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
您的代碼很好,除了一個小細節:
struct FileData
{
unique_ptr<char[]> buf;
<del>unsigned int</del> <ins>streamoff</ins> len;
};
它不能為您編譯的原因是您的編譯器尚未實現特殊移動成員的自動生成。 在完全符合C ++ 11的編譯器中, FileData
行為就像:
struct FileData
{
unique_ptr<char[]> buf;
streamoff len;
FileData(FileData&&) = default;
FileData& operator=(FileData&&) = default;
FileData(const FileData&) = delete;
FileData& operator=(const FileData&) = delete;
~FileData() = default;
};
默認的移動構造函數只是移動構造每個成員(並且類似於默認的移動分配)。
從LoadFile
返回d
,會發生一個隱式移動,它將綁定到隱式默認的移動構造函數。
使用vector<char>
或其他人建議的string
也可以使用。 但就C ++ 11而言,您的代碼沒有任何問題。
哦,我可能會這樣調整它:我希望盡可能快地擁有我的資源:
FileData LoadFile(string filename)
{
ifstream str;
str.open(filename, ios::binary);
str.seekg(0, ios::end);
auto len = str.tellg();
str.seekg(0, ios::beg);
FileData d = {unique_ptr<char[]>(new char[len]), len};
str.read(d.buf.get(), d.len);
str.close();
return d;
}
如果需要顯式定義FileData
移動成員,它應如下所示:
struct FileData
{
unique_ptr<char[]> buf;
streamoff len;
FileData(FileData&& f)
: buf(std::move(f.buf)),
len(f.len)
{
f.len = 0;
}
FileData& operator=(FileData&& f)
{
buf = std::move(f.buf);
len = f.len;
f.len = 0;
return *this;
}
};
哦,這讓我想到另一點。 默認的移動成員不完全正確,因為它們沒有在源中將len
設置為0。 如果這是一個錯誤,這取決於您的文檔。 ~FileData()
不需要len
來反映緩沖區的長度。 但其他客戶可能會。 如果你定義一個移動的FileData
沒有可靠的len
,那么默認的移動成員就可以了,否則它們不是。
我可能會使用std::vector
而不是std:::unique_ptr<char[]>
,如果你不介意在返回FileData
時復制的std::vector
:
struct FileData
{
vector<char> buf;
};
FileData LoadFile(string filename)
{
ifstream str;
str.open(filename, ios::binary);
str.seekg(0, ios::end);
auto len = str.tellg();
str.seekg(0, ios::beg);
FileData d;
d.buf.resize(len);
str.read(&(d.buf)[0], len);
str.close();
return d;
}
或者,為了避免復制,調用者可以將FileData
作為函數參數而不是返回值傳遞:
struct FileData
{
vector<char> buf;
};
void LoadFile(string filename, FileData &data)
{
ifstream str;
str.open(filename, ios::binary);
str.seekg(0, ios::end);
auto len = str.tellg();
str.seekg(0, ios::beg);
data.buf.resize(len);
str.read(&(data.buf)[0], len);
str.close();
}
如何使用std :: string作為緩沖區。 它具有您想要的所有行為:
人們會對此投票,因為它不是字符串的原始用途; 也許派生一個類(或包裝它)並稱之為'緩沖區'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.