声明与定义
变量的声明(如:extern int a;声明外部变量)告诉编译器变量名字与类型;
变量的定义:为变量分配存储空间,此时也可以给定初始值;
函数的声明:告诉编译器有这么一个函数;
函数的定义:实现函数,简言之就是带有{ };
与结构体一样,类只是一种复杂数据类型的声明,不占用内存空间。
而对象是类这种数据类型的一个变量,或者说是通过类这种数据类型定义了一个变量(对象),是占用内存空间的。
calss Point{
};
Point t1; // 将调用构造函数
Point *t1;// 不调用构造函数
声明一个指针 int *p;表示*p的类型为int,p是指向int类型的指针;(即p为int* ; *p为int)
定义 int *p 时,p位于栈区,占有内存空间是系统分配,系统将给定一个随机地址(不确定地址)给p;
void main_5()
{
int *p;
printf("0x%x \n", p);
*p = 5;
printf("%d \n", *p); // 若无上句的赋值(给确切的内存地址),将非法访问内存,程序奔溃
}
二、临时变量的产生
临时变量只在调用期间有效,有三种方式产生:
函数返回时、类型转换时、形式参数为const时;
1、函数返回时,以值或是指针形式返回时;
int sum(int a,int b)
{
return a + b;//编译器会将结果a+b的值拷贝给临时变量,最终返回的是临时变量;
}
2、在进行 强制类型转换时;
double a = 10.5;
cout << (int)a ;// 在强转时,一定生成临时变量,原始数据本身并没有改变。
cout << a;
3、函数形参为const来保护原始数据;
三、初始化
C++的初始化方式:默认初始化、值初始化、直接初始化、拷贝初始化、列表初始化;
默认初始化
1、未初始化的 全局内置类型(int、double)变量;
2、类 类型,都会执行默认构造函数;如string、vector<int>;
值初始化
值初始化是值使用了初始化器(即使用了圆括号或花括号)但却没有提供初始值的情况;
vector<int> v1(10);//10个元素,每个元素的初始化为0
vector<string> v2(10);//10个元素,每个元素都为空
vector<int> v4(10, 1);//v3有10个元素,每个的值都是1
vector<int> v3{10};//v2有1个元素,该元素的值是10
vector<int> v5{10, 1};//v4有2个元素,值分别是10和1
int *p = new int();
直接初始化
直接初始化是指采用小括号()而不使用等号=的方式进行变量初始化;
string str1(10,'9');//直接初始化
string str2(str1);//直接初始化
拷贝初始化
使用等号(赋值号=)进行初始化,编译器把等号右侧的初始值拷贝到新创建的对象中去,拷贝初始化通常使用拷贝构造函数来完成。拷贝初始化看起来像是给变量赋值,实际上是执行了初始化操作,与先定义再赋值本质不同。
int a = 0;
int a = {0};
string str1 = "hello";
string s=string("123456");
初始化列表
为C++11采用的初始化方式,使用{}进行初始化操作,下列三种情况需要用到初始化成员列表:
1、
类的数据成员中含有不带默认构造函数的
对象
(包括在继承时显示调用父类的构造函数对父类成员初始化);
2、
类的数据成员中含有
const修饰类型
的或
引用类型
;(因为这两种对象要在声明后马上初始化);
3、
子类初始化父类的私有成员;
vector<int> v4{1, -2, 3, 10, -4}; // 等价于 v4 = {1, 2, 3, ....}
int b[5]{10,20,30,40,50}; // a[] = {10,20,30,40,50};
class People{
public:
People(string n="", int a = -1) : age(a), name(n){} // 列表初始化
private:
string name;
int age;
};
注意:初始化列表中变量的执行顺序是由成员变量的声明顺序来决定的,上述并不先执行age(a),而是先执行name(n);
【举例1】
class A {
...
private:
int &a;
};
class B : public A {
...
private:
int a;
public:
const int b; // 数据成员中含有const修饰类型的或引用类型,必须通过初始化列表来初始化;
A c; // 数据成员中含有不带默认构造函数的对象,必须通过初始化列表来初始化;
static const char* d;
A* e;
};
类对象的显式初始化
Data data1(2019,9,22);//显式初始化,直接调用构造函数
Data* b = new Data(2019,9,22);//显式初始化,直接调用构造函数,使用delete时析构
Data p = Data(2019,9,22);//显式初始化,直接调用构造函数,没有临时对象,作用域结束时析构
Data B(data1);//显式初始化,调用拷贝构造函数,作用域结束时析构
类对象的隐式初始化
Data b = a;//用一个对象隐式初始化另一对象,调用拷贝构造函数,作用域结束时析构
C++11
initialize_list类模板(
初始化类模板
)
#include<initalize_list>
#include <iostream>
#include <vector>
class MyNumber
{
public:
MyNumber(const std::initializer_list<int> &v) {// C++11允许构造函数和其他函数把初始化列表当做参数。
for (auto itm : v) {
mVec.push_back(itm);
}
}
void print() {
for (auto itm : mVec) {
std::cout << itm << " ";
}
}
private:
std::vector<int> mVec;
};
int main()
{
MyNumber m{ 1, 2, 3, 4 }; // calls initializer_list
m.print(); // 1 2 3 4
MyNumber m2{ 10, 20, 30, 40 }; // calls initializer_list
m2.print(); // 10 20 30 40
return 0;
}