C++语言的简单输入输出
#include <iostream>
using namespace std;
int main()
{
char str[20];
cin >> str; //键盘输入hello world
cout << str << endl; //显示输出hello world
system("pause");
return 0;
}
输入函数:
1、cin
最基本,也是最常用的方法,接收一个字符,整形或字符串
遇到回车,TAB或空格结束
2、cin.get()
用法1:cin.get(字符变量名),可以用来接收单个字符
用法2:cin.get(字符数组名,接收字符的数目),可以用来接收一行字符串,可以包含空格
3、cin.getline()
原型:cin.getline(字符指针(char*),字符个数N(int),结束符(char));
cin.getline(字符指针(char*),字符个数N(int))
接收一行字符串,可以包含空格,与cin.get()用法2效果一样
主要适用于数组字符串,没有设置结束符默认以回车结束
cin.getline()属于istream流
4、getline()
原型:istream& getline ( istream &is , string &str , char delim(结束符) );
istream& getline ( istream &is , string &str );
用法:可以接收空格并输出,和cin.getline()类似,但cin.getline()属于istream流,getline()属于string流
getline(cin,s)获取一行字符串。
4、gets()
原型:char * gets ( char * str );
接受一个字符串,可以接收空格并输出
5、getchar()
原型:int getchar(void)
接受一个字符,这个函数在标准C里面就有,在C++里也有,是getc()的宏定义
拷贝构造函数
拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它必须的一个参数是本类型的一个引用变量。
一个拷贝构造函数简单例子
#include <iostream>
using namespace std;
class CExample {
private:
int a;
public:
//构造函数
CExample(int b)
{ a = b;}
//一般函数
void Show ()
{
cout<<a<<endl;
}
};
int main()
{
CExample A(100);
CExample B = A; //注意这里的对象初始化要调用拷贝构造函数,而非赋值
B.Show ();
return 0;
}
对象以值方式传入函数参数
#include <iostream>
using namespace std;
class CExample
{
private:
int a;
public:
//构造函数
CExample(int b)
{
a = b;
cout<<"creat: "<<a<<endl;
}
//拷贝构造
CExample(const CExample& C)
{
a = C.a;
cout<<"copy"<<endl;
}
//析构函数
~CExample()
{
cout<< "delete: "<<a<<endl;
}
void Show ()
{
cout<<a<<endl;
}
};
//全局函数,传入的是对象
void g_Fun(CExample C)
{
cout<<"test"<<endl;
}
int main()
{
CExample test(1);
//传入对象
g_Fun(test);
return 0;
}
调用g_Fun()时,会产生以下几个重要步骤:
(1).test对象传入形参时,会先会产生一个临时变量,就叫 C 吧。
(2).然后调用拷贝构造函数把test的值给C。 整个这两个步骤有点像:CExample C(test);
(3).等g_Fun()执行完后, 析构掉 C 对象。
对象以值方式从函数返回
#include <iostream>
using namespace std;
class CExample
{
private:
int a;
public:
//构造函数
CExample(int b)
{
a = b;
}
//拷贝构造
CExample(const CExample& C)
{
a = C.a;
cout<<"copy"<<endl;
}
void Show ()
{
cout<<a<<endl;
}
};
//全局函数
CExample g_Fun()
{
CExample temp(0);
return temp;
}
int main()
{
g_Fun();
return 0;
}
当g_Fun()函数执行到return时,会产生以下几个重要步骤:
(1). 先会产生一个临时变量,就叫XXXX吧。
(2). 然后调用拷贝构造函数把temp的值给XXXX。整个这两个步骤有点像:CExample XXXX(temp);
(3). 在函数执行到最后先析构temp局部变量。
(4). 等g_Fun()执行完后再析构掉XXXX对象。
浅拷贝构造函数
所谓浅拷贝,指的是在对象复制时,只对对象中的数据成员进行简单的赋值,默认拷贝构造函数执行的也是浅拷贝。大多情况下“浅拷贝”已经能很好地工作了,但是一旦对象存在了动态成员,那么浅拷贝就会出问题了。
#include <iostream>
using namespace std;
class Rect
{
public:
Rect() // 构造函数,p指向堆中分配的一空间
{
p = new int(100);
}
~Rect() // 析构函数,释放动态分配的空间
{
if(p != NULL)
{
delete p;
}
}
private:
int width;
int height;
int *p; // 一指针成员
};
int main()
{
Rect rect1;
Rect rect2(rect1); // 复制对象
return 0;
}
上面有一个bug,运行到后面,指向100的存储端有两个p,导致delete了两次100的内存空间,发生了错误。
深拷贝构造函数
在“深拷贝”的情况下,对于对象中动态成员,就不能仅仅简单地赋值了,而应该重新动态分配空间。
#include <iostream>
using namespace std;
class Rect
{
public:
Rect() // 构造函数,p指向堆中分配的一空间
{
p = new int(100);
}
Rect(const Rect& r)
{
width = r.width;
height = r.height;
p = new int; // 为新对象重新动态分配空间
*p = *(r.p);
}
~Rect() // 析构函数,释放动态分配的空间
{
if(p != NULL)
{
delete p;
}
}
private:
int width;
int height;
int *p; // 一指针成员
};
此时在rect1下的p和rect2下的p指向了不同的100存储空间。
防止默认拷贝操作
通过对对象复制的分析,我们发现对象的复制大多在进行“值传递”时发生,声明一个私有拷贝构造函数。甚至不必去定义这个拷贝构造函数,这样因为拷贝构造函数是私有的,如果用户试图按值传递或函数返回该类对象,将得到一个编译错误,从而可以避免按值传递或返回对象。
#include <iostream>
using namespace std;
class CExample
{
private:
int a;
public:
//构造函数
CExample(int b)
{
a = b;
cout<<"creat: "<<a<<endl;
}
private:
//拷贝构造,只是声明
CExample(const CExample& C);
public:
~CExample()
{
cout<< "delete: "<<a<<endl;
}
void Show ()
{
cout<<a<<endl;
}
};
//全局函数
void g_Fun(CExample C)
{
cout<<"test"<<endl;
}
int main()
{
CExample test(1);
//g_Fun(test); 按值传递将出错
return 0;
}