因为我的类之间存在循环依赖关系,我的Node看起来像
struct Node{
Word * data;
Node * next;
};
所以当我创建一个新的Node时(w是一个Word类型,newptr是该类的数据成员)
newptr = new Node;
newptr-> data = &w;
newptr-> next = NULL;
如果我想访问链表的第一个节点中的数据,我认为正确的方法是
Word retVal;
Node *temp;
temp = head->next;
retVal = temp->data;
return retVal;
但是,数据是指向Word类型的指针,它本身不是Word类型。但我想要返回一个Word,而不是一个Word指针。那么我可以添加Word * word;
然后word = temp->data;
和retVal = *word;
吗?我的测试程序告诉我一路上做的事情是错误的,因为当我到达函数时我遇到了分段错误。我正在尝试这个
Word retVal;
Word * word;
Node *temp;
temp = head->next;
word = temp->data;
retVal = *word;
return retVal;
在不同地方使用cout线我知道我的错误发生在word = temp->data
行
我的Word类成员按要求:
class Word{
public:
char * charArray;
char * sendBack; //ignore
char * rest; //ignore
bool isPigLatin;
bool firstIsVowel;
Word();
Word(const Word& w);
Word(char array[], int size);
~Word();
void show(); //ignore
//ignore everything below
friend ostream& operator<< (ostream& out, const Word& w);
Sentence operator+ (Sentence s);
Sentence operator+ (Word w);
void operator+ (int i);
Word& operator++(int);
Word& operator++();
Word& operator--(int);
Word& operator--();
};
很多这些事情与链接列表本身没有关系,但我包含了所有内容以防万一
按照要求复制Word的构造函数:
Word::Word(const Word& w){
cout << "Copy constructor for Word" << endl;
int size = 0;
while(w.charArray[size]){
size++;
}
charArray = new char[size + 1]; //+1 for \0 at end
int i = 0;
while(w.charArray[i]){
charArray[i] = w.charArray[i];
i++;
}
if(!w.isPigLatin){
isPigLatin = false;
}
else{
isPigLatin = true;
}
}
firstIsVowel,sendBack和rest在它们需要用于++和 - 重载之前不会被声明,因为它们用于生成猪拉丁文并回到英语中
我的构造函数:
Word::Word(char array[], int size){
//In my test code I am hard coding a char array and its size, for the actual program I read in the char array from a file, then go thru the char array to get the size before calling Word(char c[], int s)
cout << "Character Array Word constructor" << endl;
int i = 0;
charArray = new char[size];
while(array[i]){
charArray[i] = array[i];
i++;
}
isPigLatin = false;
//this is needed for my Pig Latin function. All words will be read in as English, thus Piglatin = false. If the function to change PigLatin into English is called, nothing will happen since this is false. It gets set to true in the function that changes English to Pig Latin
}
和默认构造函数
Word::Word(){
cout << "Default constructor for Word" << endl;
charArray = new char[1];
sentBack = new char[1];
rest = new char[1];
}
答案 0 :(得分:1)
看看每行代码本身在做什么:
首先,您要在堆上分配一个Node对象,并将其地址值存储在名为&#39; temp&#39;
的指针变量中temp = new Node;
其次,您通过覆盖其地址值来泄漏该内存,将该地址值替换为&#39; head&#39;中包含的地址值。指针变量。
temp = head;
第三,您在“临时”中覆盖了地址值。再次通过存储链表中第二项的地址
temp = temp->next;
事实上,您可以用以下内容替换这3行:
temp = head->next;
您已经有可能在此处出现错误,因为无法保证head
不为空,因此您可以通过针对null检查代码来改进代码。
接下来,当您在delete
变量上调用temp
时,列表中的第二个节点将被释放;将第一个节点留在列表中,其中包含&#34;悬空&#34;其next
指针的值(无效)。
但是,由于您之后的所有内容都是第一个节点,(并且假设您要删除第一个节点,而不是第二个节点),您可能想要这样做:
Word* retVal = nullptr;
if (head != nullptr)
{
// (1) Remember the address-of the first node for later deletion
Node* temp = head;
// (2) The second node becomes the new head
head = head->next;
// (3) Grab the data from the old head
retVal = temp->data;
// (4) Release the memory for the old head
delete temp;
}
return retVal;
答案 1 :(得分:1)
您声明要返回Word
个对象。假定对象包含指向动态分配内存的指针,则需要正确复制它。
正确的副本意味着副本必须与原始对象无法区分。对于您的情况,这意味着需要将源对象中的 all 成员分配给目标对象。您的代码无法为两个指针成员(sendBack
和rest
)以及一个bool firstIsVowel
执行此操作。
让我们抛弃两个指针变量并假设Word
没有它们。复制构造函数看起来像这样:
Word::Word(const Word& w) : isPigLatin(w.isPigLatin), firstIsVowel(w.firstIsVowel)
{
int size = strlen(w.charArray);
charArray = new char[size + 1];
strcpy(charArray, w.charArray);
}
请注意,我直接从传入的对象复制了所有成员。没有“商业逻辑”,也没有愚弄这些bool的价值,没什么。刚复制过。这是复制构造函数的工作和唯一工作。
其次,您需要一个赋值运算符。赋值运算符的签名如下:
Word& operator = (const Word& w);
换句话说,您需要能够将Word分配给另一个Word。这可以这样写:
Word& Word::operator=(const Word& w)
{
Word temp(w);
std::swap(isPigLatin, temp.isPigLatin);
std::swap(firstIsVowel, temp.firstIsVowel);
std::swap(charArray, temp.charArray);
return *this;
}
这使用复制/交换习语,在SO上的许多链接中描述。我不会进入它,但它确实要求你有Word
的工作副本构造函数和析构函数来实现它。 std::swap
是一个实用函数,可以交换这两个值。
所以如果我们删除无关的两个char指针,这应该照顾Word
的复制。如果它们必须在那里,那么你需要修改上面的代码来正确地分配和复制这两个指针的数据。