[英]Deallocating memory
對於一個項目,我必須實現一個bitset類。 到目前為止,我的代碼是:
頭文件
#ifndef BITSET_H_
#define BITSET_H_
#include <string>
#include <cmath>
using namespace std;
// Container class to hold and manipulate bitsets
class Bitset {
public:
Bitset();
Bitset(const string);
~Bitset();
// Returns the size of the bitset
int size();
// Sets a bitset equal to the specified value
void operator= (const string);
// Accesses a specific bit from the bitset
bool operator[] (const int) const;
private:
unsigned char *bitset;
int set_size;
// Sets a bitset equal to the specified value
void assign(const string);
};
#endif /* BITSET_H_ */
源文件
#include "bitset.h"
Bitset::Bitset() {
bitset = NULL;
}
Bitset::Bitset(const string value) {
bitset = NULL;
assign(value);
}
Bitset::~Bitset() {
if (bitset != NULL) {
delete[] bitset;
}
}
int Bitset::size() {
return set_size;
}
void Bitset::operator= (const string value) {
assign(value);
}
bool Bitset::operator[] (const int index) const {
int offset;
if (index >= set_size) {
return false;
}
offset = (int) index/sizeof(unsigned char);
return (bitset[offset] >> (index - offset*sizeof(unsigned char))) & 1;
}
void Bitset::assign(const string value) {
int i, offset;
if (bitset != NULL) {
delete[] bitset;
}
bitset = new unsigned char[(int) ceil(value.length()/sizeof(unsigned char))];
for (i = 0; i < value.length(); i++) {
offset = (int) i/sizeof(unsigned char);
if (value[i] == '1') {
bitset[offset] |= (1 << (i - offset*sizeof(unsigned char)));
} else {
bitset[offset] &= ~(1 << (i - offset*sizeof(unsigned char)));
}
}
set_size = value.length();
}
我的問題是我在解構函數和分配方法核心轉儲中的刪除語句。 不必重新分配此內存嗎? 到目前為止,根據我所讀的內容,每次調用new時總是需要使用delete命令。
編輯:我已經更改了上面的代碼以反映其中一種修復方法。 我在構造函數中添加了bitset = NULL。 這修復了assign方法中的核心轉儲,但是我在解構函數中仍然遇到錯誤。
我認為您應該在第二個構造函數中將bitset
初始化為NULL
。
為什么?
因為指針變量不一定要初始化為NULL
。 因此,當您使用第二個構造函數時,您可能試圖delete[]
一些隨機內存地址。
因此,您應該具有:
Bitset::Bitset(const string value) : bitset(NULL)
{
assign(value);
}
您很可能是在某個地方復制Bitset
。 您尚未定義副本構造函數,而不是副本分配運算符。 復制的結果是,您有兩個實例,他們兩個都認為他們應該在完成時取消分配動態分配的數組。
這被稱為三規則 :如果您定義析構函數,復制構造函數或復制賦值運算符中的任何一個,則很有可能需要定義所有三個 。
現在,關於您的代碼:
#include "bitset.h"
好。
Bitset::Bitset() {
bitset = NULL;
}
(1)您沒有包含保證定義為NULL
的標頭。
(2)您沒有初始化成員set_size
,因此索引運算符中的檢查可能/將使用不確定值(具有不確定行為)。
(3)通常更喜歡使用初始化列表而不是賦值(這避免了例如先進行默認構造后賦值)。
Bitset::Bitset(const string value) {
bitset = NULL;
assign(value);
}
(4)一般來說,用作業來表達構造不是一個好主意。 取而代之的是根據構造表達作業。
Bitset::~Bitset() {
if (bitset != NULL) {
delete[] bitset;
}
}
(5)不需要檢查NULL
; 您可以安全地delete
一個空指針。
int Bitset::size() {
return set_size;
}
(6)嗯,好吧, set_size
是未初始化的成員……而且,此成員函數應為const
。
void Bitset::operator= (const string value) {
assign(value);
}
(7)賦值運算符通常應返回對分配對象的引用。 那只是一個約定,但這是您的班級用戶所期望的。
(8)通過值或引用const
傳遞參數。 通常,對於內置類型,請選擇按值;對於其他類型,例如std::string
,請選擇對const
引用。 也就是說,形式參數最好是string const& value
。
bool Bitset::operator[] (const int index) const {
int offset;
if (index >= set_size) {
return false;
}
offset = (int) index/sizeof(unsigned char);
return (bitset[offset] >> (index - offset*sizeof(unsigned char))) & 1;
}
(9)首先,再次是未初始化的set_size
成員。
(10)然后,請注意, sizeof(unsigned char)
根據定義為1。 您可能要在此處使用<limits.h>
CHAR_BIT
。 或僅使用8,除非計划支持Unisys計算機(9位字節)或德州儀器數字信號處理器(16位字節)。
void Bitset::assign(const string value) {
int i, offset;
if (bitset != NULL) {
delete[] bitset;
}
(11)不需要檢查NULL
。
bitset = new unsigned char[(int) ceil(value.length()/sizeof(unsigned char))];
(12)如前所述, sizeof(char)
根據定義為1。
(13)除法具有整數參數,整數除法也是如此,而不是浮點除法。 大概您想要的是把戲(a+b-1)/b
?
for (i = 0; i < value.length(); i++) {
(14)樣式:在實際可行的情況下聲明一個盡可能接近其首次使用的變量。 這意味着直接在循環頭中聲明循環計數器i
,如下所示: for( int i = 0, ...
offset = (int) i/sizeof(unsigned char);
(14)同上,以offset
。 但是對於此變量,您不打算更改其值,因此也請聲明為const
。
if (value[i] == '1') {
bitset[offset] |= (1 << (i - offset*sizeof(unsigned char)));
} else {
bitset[offset] &= ~(1 << (i - offset*sizeof(unsigned char)));
}
(15)最好重新考慮那些換檔操作!
}
set_size = value.length();
}
干杯,……
確保分配大小不為零,我懷疑這是這里發生的事情,並且您只是在寫入未分配的垃圾內存。 在valgrind下運行也會捕捉到這一點。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.