C++-一个函数会使其他函数发生故障
C++ - one function makes others malfunction
这是我的任务:
编写类Word,该类具有:
- 字符数组上的指针
- 构造函数和析构函数
- 读取单词的函数
- 函数检查作为参数传递给它的字符是否出现在单词中,并返回出现的位置
- 函数,用于检查两个单词中哪一个出现次数更多的数字10,并返回出现次数
这是我的解决方案。我编译它没有错误,但它并没有按预期工作。
#include <iostream>
#include <string.h>
using namespace std;
class Word
{
private:
char *content;
int length;
public:
Word();
Word(char *);
~Word();
void print_content(void);
int check_character(char);
friend int check_number(Word,Word);
};
Word::Word()
{
}
Word::Word(char *n)
{
length=strlen(n);
content=new char [length];
for(int i=0;i<length;i++)
{
content[i]=n[i];
}
}
Word::~Word()
{
delete content;
}
void Word::print_content(void)
{
for(int i=0;i<length;i++)
{
cout<<""<<content[i];
}
}
int Word::check_character(char a)
{
int position=0;
for(int i=0;i<length;i++)
{
if(content[i]==a)
{
position=i+1;
}
}
if(position>0)
{
return position;
}
else return 0;
}
int check_number(Word n,Word m)
{
int counter_n=0;
int counter_m=0;
for(int i=1;i<n.length;i++)
{
if((n.content[i-1]=='1')&&(n.content[i]=='0'))
{
counter_n=counter_n+1;
}
}
for(int i=1;i<m.length;i++)
{
if((m.content[i-1]=='1')&&(m.content[i]=='0'))
{
counter_m=counter_m+1;
}
}
if(counter_n>counter_m)
{
return counter_n;
}
else if(counter_n<counter_m)
{
return counter_m;
}
else return 0;
}
int main()
{
char characters1[]="qwerty10",*p1,*p2;
char characters2[]="stackoverflow101010";
p1=characters1;
p2=characters2;
Word first(p1);
Word second(p2);
cout<<""<<first.check_character('q')<<endl;
cout<<""<<second.check_character('f')<<endl;
//cout<<""<<check_number(first,second)<<endl;
first.print_content();
second.print_content();
}
由于某种原因,函数check_number(first,second)会使其他函数无法正常工作,如果您通过删除"//"来调用它,您会看到第一个.print_content()和第二个.print/content(。或者,如果函数first.check_character('r')首先被调用,第二个.check_charter('j')第二个被调用,然后check_number(first,second),那么两个第一次被调用的函数将不起作用。这种奇怪行为的原因是什么?
Word
对象通过复制传递给check_number
,但您没有定义复制构造函数。所以编译器使用默认的一个,而这个复制指针(char* content
)。传递给函数的临时对象指向主函数中创建的数据first
和second
。。。在删除时(临时对象在调用函数后被删除),它们会删除指针,因此first
和second
对象指向已删除的内存。你在这里有未确定的行为,这解释了你所经历的副作用。
通过引用check_number
传递对象是解决问题的一种简单方法。以下是一个工作代码(包括许多修复,因为您没有正确访问数组):
#include <iostream>
using namespace std;
#include <iostream>
#include <string.h>
using namespace std;
class Word
{
private:
char *content;
int length;
public:
Word();
Word(char *);
~Word();
void print_content(void);
int check_character(char);
friend int check_number(const Word&,const Word&); // changed here
};
Word::Word()
{
}
Word::Word(char *n)
{
length=strlen(n);
content=new char [length];
for(int i=0;i<length;i++)
{
content[i]=n[i]; // changed here
}
}
Word::~Word()
{
delete [] content; // changed here
}
void Word::print_content(void)
{
for(int i=0;i<length;i++)
{
cout<<""<<content[i]; // changed here
}
}
int Word::check_character(char a)
{
int position=0;
for(int i=0;i<length;i++)
{
if(content[i]==a) // changed here
{
position=i+1;
}
}
if(position>0)
{
return position;
}
else return 0;
}
int check_number( const Word& n, const Word& m)// changed here
{
int counter_n=0;
int counter_m=0;
for(int i=1;i<n.length;i++)
{
if((n.content[i-1]=='1')&&(n.content[i]=='0')) // changed here
{
counter_n=counter_n+1;
}
}
for(int i=1;i<m.length;i++)
{
if((m.content[i-1]=='1')&&(m.content[i]=='0')) // changed here
{
counter_m=counter_m+1;
}
}
if(counter_n>counter_m)
{
return counter_n;
}
else if(counter_n<counter_m)
{
return counter_m;
}
else return 0;
}
int main()
{
char characters1[]="qwerty10",*p1,*p2;
char characters2[]="stackoverflow101010";
p1=characters1;
p2=characters2;
Word first(p1);
Word second(p2);
cout<<""<<first.check_character('q')<<endl;
cout<<""<<second.check_character('f')<<endl;
cout<<""<<check_number(first,second)<<endl;
first.print_content();
second.print_content();
}
该输出:
1
10
3
qwerty10stackoverflow101010
声明复制构造函数是解决问题的另一种方法:
Word( const Wodr& word ) :
length( word.length ),
content( new char[word.length] )
{
memcpy( content, word.content, word.length );
}
这将比通过const引用传递对象效率低,但会使代码更安全(最好始终声明复制构造函数,以防止您在这里遇到错误)。
最后,如果你懒惰,你也可以将复制构造函数声明为私有的,以防止编译器复制对象,只需声明它,而不是强制执行它:
class Word
{
....
private:
Word( const Word& word ); // this makes argument passed by copy impossible.
};
然后,编译器将不允许您调用check_number。
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 为什么我不能在 C++ 中的特定函数重载中调用同一函数的任何其他重载?
- 保留对其他类的成员函数的引用
- 为什么将值返回函数传递给重载=运算符对运算符函数有效,而对其他运算符无效
- 如何在其他文件中使用函数
- C++变量名(可以将 main 声明为变量,但对于其他函数名称则不然)
- 如何封装一个函数,以便它只能由同一类中的一个其他函数调用?
- 为什么 memcpy() 和其他类似的函数使用汇编?
- 为什么 c++ 中的 main() 函数不采用除 int 和 void 之外的任何其他返回类型
- 泛型枚举和其他类型的重载模板函数
- error dllimport 函数的定义不允许在一个特定的联合中,而其他类、结构和联合将按预期导出
- 将基类的成员函数重载到其他派生类C++
- 如何在其他类中使用参数化构造函数制作类的对象?
- 为什么 ADL 的运算符函数行为与其他函数不同?
- 没有头文件如何使用c ++调用其他模块中的函数?
- 在C++单元测试上下文中,抽象基类是否应将其他抽象基类作为函数参数
- 如何制作 cmakelists.txt编译使用在其他地方声明和实现的函数和类的 CPP
- 成员函数不能为集合迭代器和const_iterator的输入重载(但可以为其他 STL 迭代器重载)
- 通过向构造函数其他对象引用页面来创建对象