#ifndef WRONG_H_ #define WRONG_H_ class Wrong { private: char * str; //存储数据 int len; //字符串长度 public: Wrong(const char * s); //构造函数 Wrong(); // 默认构造函数 ~Wrong(); // 析构函数 friend ostream & operator<<(ostream & os,const Wrong& st); }; #endif Wrong.cpp: #include <iostream> #include <cstring> #include "wrong.h" using namespace std; Wrong::Wrong(const char * s) { len = strlen(s); str = new char[len + 1]; strcpy(str, s); }//拷贝数据 Wrong::Wrong() { len =0; str = new char[len+1]; str[0]='\0'; } Wrong::~Wrong() { cout<<"这个字符串将被删除:"<<str<<'\n';//为了方便观察结果,特留此行代码。 delete [] str; } ostream & operator<<(ostream & os, const Wrong & st) { os << st.str; return os; } test_right.cpp: #include <iostream> #include <stdlib.h> #include "Wrong.h" using namespace std; int main() { Wrong temp("天极网"); cout<<temp<<'\n'; system("PAUSE"); return 0; } |
#include <iostream> #include <stdlib.h> #include "Wrong.h" using namespace std; void show_right(const Wrong&); void show_wrong(const Wrong);//注意,参数非引用,而是按值传递。 int main() { Wrong test1("第一个范例。"); Wrong test2("第二个范例。"); Wrong test3("第三个范例。"); Wrong test4("第四个范例。"); cout<<"下面分别输入三个范例:\n"; cout<<test1<<endl; cout<<test2<<endl; cout<<test3<<endl; Wrong* wrong1=new Wrong(test1); cout<<*wrong1<<endl; delete wrong1; cout<<test1<<endl;//在Dev-cpp上没有任何反应。 cout<<"使用正确的函数:"<<endl; show_right(test2); cout<<test2<<endl; cout<<"使用错误的函数:"<<endl; show_wrong(test2); cout<<test2<<endl;//这一段代码出现严重的错误! Wrong wrong2(test3); cout<<"wrong2: "<<wrong2<<endl; Wrong wrong3; wrong3=test4; cout<<"wrong3: "<<wrong3<<endl; cout<<"下面,程序结束,析构函数将被调用。"<<endl; return 0; } void show_right(const Wrong& a) { cout<<a<<endl; } void show_wrong(const Wrong a) { cout<<a<<endl; } |
运行结果:
下面分别输入三个范例:
第一个范例。
第二个范例。
第三个范例。
第一个范例。
这个字符串将被删除:第一个范例。
使用正确的函数:
第二个范例。
第二个范例。
使用错误的函数:
第二个范例。
这个字符串将被删除:第二个范例。
这个字符串将被删除:?=
?=
wrong2: 第三个范例。
wrong3: 第四个范例。
下面,程序结束,析构函数将被调用。
这个字符串将被删除:第四个范例。
这个字符串将被删除:第三个范例。
这个字符串将被删除:?=
这个字符串将被删除:x =
这个字符串将被删除:?=
这个字符串将被删除:
现在,请大家自己试试运行结果,或许会更加惨不忍睹呢!下面,我为大家一一分析原因。
首先,大家要知道,C++类有以下这些极为重要的函数:
一:复制构造函数。
二:赋值函数。
我们先来讲复制构造函数。什么是复制构造函数呢?比如,我们可以写下这样的代码:Wrong test1(test2);这是进行初始化。我们知道,初始化对象要用构造函数。可这儿呢?按理说,应该有声明为这样的构造函数:Wrong(const Wrong &);可是,我们并没有定义这个构造函数呀?答案是,C++提供了默认的复制构造函数,问题也就出在这儿。
(1):什么时候会调用复制构造函数呢?(以Wrong类为例。)
在我们提供这样的代码:Wrong test1(test2)时,它会被调用;当函数的参数列表为按值传递,也就是没有用引用和指针作为类型时,如:void show_wrong(const Wrong),它会被调用。其实,还有一些情况,但在这儿就不列举了。
(2):它是什么样的函数。
它的作用就是把两个类进行复制。拿Wrong类为例,C++提供的默认复制构造函数是这样的:
Wrong(const Wrong& a) { str=a.str; len=a.len; } |
Wrong* wrong1=new Wrong(test1); cout<<*wrong1<<endl; delete wrong1; |
cout<<"使用错误的函数:"<<endl; show_wrong(test2); cout<<test2<<endl;//这一段代码出现严重的错误! |
Wrong::Wrong(const Wrong& a) { len=a.len; str=new char(len+1); strcpy(str,a.str); } |
Wrong wrong3; wrong3=test4; |
Wrong& Wrong::operator=(const Wrong& a) { delete [] str;//先删除自身的数据 len=a.len; str=new char[len+1]; strcpy(str,a.str);//此三行为进行拷贝 return *this;//返回自身的引用 } |
Wrong& Wrong::operator=(const Wrong& a) { if(this==&a) return *this; delete [] str; len=a.len; str=new char[len+1]; strcpy(str,a.str); return *this; } |
把这些代码加入程序,问题就完全解决,下面是运行结果:
下面分别输入三个范例:
第一个范例
第二个范例
第三个范例
第一个范例
这个字符串将被删除:第一个范例。
第一个范例
使用正确的函数:
第二个范例。
第二个范例。
使用错误的函数:
第二个范例。
这个字符串将被删除:第二个范例。
第二个范例。
wrong2: 第三个范例。
wrong3: 第四个范例。
下面,程序结束,析构函数将被调用。
这个字符串将被删除:第四个范例。
这个字符串将被删除:第三个范例。
这个字符串将被删除:第四个范例。
这个字符串将被删除:第三个范例。
这个字符串将被删除:第二个范例。
这个字符串将被删除:第一个范例。
关于动态内存分配的问题就介绍到这儿,希望大家都能热爱编程,热爱C++!