是我4句话5个ERROR,阿巴阿巴
001_arrpointer.cc
cpp
#include <iostream>
using std::cout;
using std::endl;
void test(){
int a[5]={1,2,3,4,5};
int (*p)[5]=&a;
cout<<p<<endl;
cout<<p+1<<endl;
int *pp=(int*)(&a+1);
//第二个数组的首地址(*int)[5],强转成int*
//变成第二个数组的首元素的地址
cout<<*(a+1)<<" "<<*(pp-1)<<endl;
}
int main(void)
{
test();
return 0;
}
01,引用
reference.cc
cpp
#include <iostream>
using std::cout;
using std::endl;
void test(){
int num=100;
int & ref=num;
//& 不代表取值符,代表引用符号
cout<<ref<<endl;
ref=1000000;
cout<<ref<<endl;
int num2=200;
ref=num2;//赋值
int *p=#
cout<<&num<<endl;
cout<<&ref<<endl;//底层 cosnt poiter
cout<<&p<<endl;
cout<<&num2<<endl;
/* 特殊的常量指针,无法对其进行访问,只能间接访问到指向的对象/地址 */
cout<<endl;
const int & ref1=num;
/* ref1=num2; */
/* 不希望通过引用改变其本体,const */
}
int main(void)
{
test();
return 0;
}
swap.cc
cpp
#include <iostream>
using std::cout;
using std::endl;
void swap(int x,int y){
}
void swap1(int *px,int *py){
int z=*px;
*px=*py;
*py=z;
}
//int & a=x,int & b=y
void swap2(int & a,int &b){
int temp=a;
a=b;
b=temp;
}
int num=100;
int func1(){
return num; //执行return 语句的时候会发生copy
}
int & func2(){
//如果某个函数需要让其返回值是某个变量本身
//那么可以在函数返回类型中加上&
return num; //no copy
}
#if 0
int & func(){
int num=1;
return num;
//num被销毁,悬空引用
//确保引用绑定的本体的生命周期比函数更长
}
#endif
int & func4(){
int *p=new int(10);
return *p; //no delete
}
void test(){
int x=6,y=90;
swap2(x,y);
cout<<"x="<<x<<" y="<<y<<endl;
swap1(&x,&y);
cout<<"x="<<x<<" y="<<y<<endl;
cout<<endl;
cout<<&num<<endl;
cout<<func1()<<endl; //临时变量
cout<<func2()<<endl; //绑定到num的引用
cout<<&func2()<<endl;//对本体进行访问
int & ref=func4();
cout<<ref<<endl;
delete &ref;
//回收
}
int main(void)
{
test();
return 0;
}
02,强制转换
typecast.cc 靓仔迷惑
cpp
#include <iostream>
#include <stdlib.h>
using std::cout;
using std::endl;
void test(){
int *p=(int*)malloc(sizeof(int));
*p=100;
free(p);
p=nullptr;
int *p1=static_cast<int*>(malloc(sizeof(int)));
*p1=100;
free(p1);
p1=nullptr;
cout<<endl;
const int num=10;
/* int a=const_cast<int>(num); */
/* int a=const_cast<int>(10); */
//把能const int -->int
const int *pp=#
int *p2=const_cast<int*>(pp);
//作用于 const引用和指向常量的指针
*p2=100;
cout<<*p2<<endl; //100
cout<<num<<endl; //10
cout<<p2<<endl;
cout<<&num<<endl;
}
int main(void)
{
test();
return 0;
}
03,函数重载 04,默认参数
overload.cc
cpp
#include <iostream>
using std::cout;
using std::endl;
//函数重载
//编译器的名字改变机制将函数的名字改编成了与参数信息相关的名字
int add(int x,int y){cout<<"int+int"<<" \t\t"; return x+y;}
int add(int x,int y,int z){cout<<"int+int+int"<<" \t\t"; return x+y+z;}
double add(double x,double y){cout<<"double+double"<<" \t\t"; return x+y;}
double add(int x,double y){cout<<"int+double"<<" \t\t"; return x+y;}
double add(double x,int y){cout<<"double+int"<<" \t\t"; return x+y;}
/* void add(int x,double y){cout<<"int+double"<<" "; } */
//用C的方式编译函数
//不可以进行函数重载
extern "C"{
int func(int x,int y){cout<<"int+int"<<" "; return x+y;}
/* int func(int x,int y,int z){cout<<"int+int+int"<<" "; return x+y+z;} */
int func01(int x,int y,int z){cout<<"int+int+int"<<" "; return x+y+z;}
}
/* void ffunc(int x,int y){ */
/* cout<<"x="<<x<<"\t\t"; */
/* cout<<"y="<<y<<endl; */
/* } */
/* void ffunc(int x,int y=6){ */
/* cout<<"x="<<x<<"\t\t"; */
/* cout<<"y="<<y<<endl; */
/* }//备胎 */
void ffunc(int x=9090,int y=6){
cout<<"x="<<x<<"\t\t";
cout<<"y="<<y<<endl;
}//备胎
/* void ff(int x=10086,int y); */
void ff(int x,int y=10086);
//实现与声明分离,建议默认值给声明
//顺序默认从右到左
int dd(int x,int y,int z=100){cout<<"int+int+int"<<" \t\t"; return x+y+z;}
int dd(int x,int y){cout<<"int+int"<<" \t\t"; return x+y;}
//函数重载+默认值,可能会引发冲突
void test(){
cout<<add(1,2)<<endl;
cout<<add(1,2,3)<<endl;
cout<<add(1.5,2.5)<<endl;
cout<<add(1,2.5)<<endl;
cout<<add(1.3333,2)<<endl;
cout<<add(1,2.77)<<endl;
//缺省调用
ffunc(10,9);
ffunc(2);
ffunc();
ff(10,9);
ff(10);
cout<<dd(10,10,10)<<endl;
/* dd(10,10); */
}
void ff(int x,int y){
cout<<"x="<<x<<"\t\t";
cout<<"y="<<y<<endl;
}//备胎
int main(void)
{
test();
return 0;
}
05,BOOL类型
bool.cc
cpp
#include <iostream>
using std::cout;
using std::endl;
void test(){
int x=true;
int y=false;
cout<<x<<endl;
cout<<y<<endl;
bool b1=1;
bool b2=100;
bool b3=0;
bool b4=-1;
cout<<b1<<endl;
cout<<b2<<endl;
cout<<b3<<endl;
cout<<b4<<endl;
// 1 1 0 1
if(b4){cout<<"i love xixi"<<endl;}
cout<<sizeof(b4)<<endl;
}
int main(void)
{
test();
return 0;
}
06,INLINE函数
inline.cc 头文件需要声明和定义写一起
cpp
#include <iostream>
using std::cout;
using std::endl;
//宏定义函数,不会检查,只替换
#define MAX(a,b) (a)>(b)?(a):(b)
#define MIN(a,b) {(a)>(b)?(a):(b)}
//内联函数
//建议替换,(可能不采纳)
//更高级的替换,有安全检查机制
inline int max(int x,int y){
return x>y?x:y;
}
void test(){
/* cout<<MAX(20,10)+20<<endl; */
/* cout<<MAX(10,20)+20<<endl; */
/* cout<<MIN(20,10)+20<<endl; */
/* cout<<MIN(10,20)+20<<endl; */
//不是哥们,4句话 5个error
cout<<max(20,10)+20<<endl;
cout<<max(10,20)+20<<endl;
}
int main(void)
{
test();
return 0;
}
07,异常处理
catch.cc
cpp
#include <iostream>
using std::cout;
using std::endl;
double division(double x,double y){
if(y==0){
throw "0 been division";
}else if(x==0){
throw 1.1;
}
return x/y;
}
void test(){
try{
double x=0,y=100;
cout<<division(x,y)<<endl;
cout<<"over"<<endl;
}
catch(const char*){
/* cout<<msg<<endl; */
cout<<" errr!!!!!"<<endl;}
catch(double a){cout<<a<<endl;}
cout<<"i love xixi"<<endl;
}
int main(void)
{
test();
return 0;
}
08,内存布局
cpp
#include <iostream>
using std::cout;
using std::endl;
const int xixi=90;
int gNum=1;
const int gcNum=20;
void test(){
int num=100;
int num2=200;
const int xixi1=100;
cout<<&num<<endl;
cout<<&num2<<endl;
cout<<endl;
cout<<&xixi<<endl; //全局常量:文字常量区
cout<<&xixi1<<endl; //局部常量 :staic
cout<<endl;
int *p=new int(20);
int *p1=new int(30);
cout<<p<<endl;
cout<<p1<<endl;
cout<<endl;
cout<<&gNum<<endl;
static int sNum=18;
cout<<&sNum<<endl;
cout<<endl;
const char* pstr="i love xixi";
cout<<pstr<<endl;
printf("%p\n",pstr);
//输出流运算符对char*的运算重载效果
const int aaa=90909;
/* int *const pp=&aaa; */
const int * pp=&aaa;
cout<<pp<<endl;
cout<<endl;
cout<<static_cast<void*>(const_cast<char*>(pstr))<<endl;
cout<<"&gcNum"<<&gcNum<<endl;
cout<<endl;
printf("%p\n",&test);
}
int main(void)
{
test();
cout<<endl;
printf("%p\n",&main);
return 0;
}
09,C风格字符串
cpp
#include <iostream>
#include <cstring>
using std::cout;
using std::endl;
void test(){
char arr[3]={'i','s','\0'};
char arr1[]={'a','q'};
char arr2[]="i love xixi";
cout<<arr<<endl;
cout<<arr1<<endl;
cout<<arr2<<endl;
printf("%p\n",arr);
printf("%p\n",arr1);
printf("%p\n",arr2);
/* 0x7fff73681fd9 */
/* 0x7fff73681fd7 */
/* 0x7fff73681fdc */
//char * arr te shu xiao guo1
const char* pp="i love xixi pp";
/* char* pp="hello"; */
/* pp[0]='H'; */
//段错误
cout<<pp<<endl;
cout<<endl;
const char* ps="i love xixxi ps";
char* pssss=new char[strlen(ps)+1]();
strcpy(pssss,ps);
const char* pppp=new char[10]{'h','e','l','l','o'};
cout<<pppp<<endl;
cout<<pssss<<endl;
delete [] pssss;
pssss=nullptr;
delete [] pppp;
pppp=nullptr;
}
int main(void)
{
test();
return 0;
}
10,作业
01,在( )情况下适宜采用inline
定义内联函数。(多选题)
-
A 函数体含有循环语句
-
B 函数体含有递归语句
-
C 函数代码少、频繁调用
-
D 函数代码多、不常调用
-
E 需要加快程序执行速度
02,写出下面程序的运行结果。 10/26 26/10 10/26 25/11
cpp
#include <iostream>
using std::cout;
using std::endl;
void f2(int &x, int &y)
{
int z = x;
x = y;
y = z;
}
void f3(int *x, int *y)
{
int z = *x;
*x = *y;
*y = z;
}
int main()
{
int x, y;
x = 10; y = 26;
cout << "x, y = " << x << ", " << y << endl;
f2(x, y);
cout << "x, y = " << x << ", " << y << endl;
f3(&x, &y);
cout << "x, y = " << x << ", " << y << endl;
x++; // ++x
y--;
f2(y, x);
cout << "x, y = " << x << ", " << y << endl;
return 0;
}
03,C++内存布局是怎样的?可以具体阐述一下么?
1,栈区
操作系统控制,高地址--》低地址(编译器优化显得低地址--》高地址)
2,堆区
程序员分配,低地址--》高地址,和栈区没有明确的界限
3,全局/静态区
读写段(数据段)存全局、静态变量
4,文字常量区
只读段,存程序中直接使用的文字常量和全局常量
5,程序代码区
只读段,存放函数体的二进制代码
04,在自定义命名空间MySpace中定义add函数,能够实现多个数据的加法(两个int、一个double一个int、一个int一个double、三个int),并跨模块调用add函数,使用using声明机制验证其功能。还可以适当给函数参数赋默认值,进行缺省调用的练习。
cpp
#include <iostream>
using std::cout;
using std::endl;
//函数重载
//编译器的名字改变机制将函数的名字改编成了与参数信息相关的名字
int add(int x,int y){cout<<"int+int"<<" \t\t"; return x+y;}
int add(int x,int y,int z){cout<<"int+int+int"<<" \t\t"; return x+y+z;}
double add(double x,double y){cout<<"double+double"<<" \t\t"; return x+y;}
double add(int x,double y){cout<<"int+double"<<" \t\t"; return x+y;}
double add(double x,int y){cout<<"double+int"<<" \t\t"; return x+y;}
/* void add(int x,double y){cout<<"int+double"<<" "; } */
//用C的方式编译函数
//不可以进行函数重载
extern "C"{
int func(int x,int y){cout<<"int+int"<<" "; return x+y;}
/* int func(int x,int y,int z){cout<<"int+int+int"<<" "; return x+y+z;} */
int func01(int x,int y,int z){cout<<"int+int+int"<<" "; return x+y+z;}
}
/* void ffunc(int x,int y){ */
/* cout<<"x="<<x<<"\t\t"; */
/* cout<<"y="<<y<<endl; */
/* } */
/* void ffunc(int x,int y=6){ */
/* cout<<"x="<<x<<"\t\t"; */
/* cout<<"y="<<y<<endl; */
/* }//备胎 */
void ffunc(int x=9090,int y=6){
cout<<"x="<<x<<"\t\t";
cout<<"y="<<y<<endl;
}//备胎
/* void ff(int x=10086,int y); */
void ff(int x,int y=10086);
//实现与声明分离,建议默认值给声明
//顺序默认从右到左
int dd(int x,int y,int z=100){cout<<"int+int+int"<<" \t\t"; return x+y+z;}
int dd(int x,int y){cout<<"int+int"<<" \t\t"; return x+y;}
//函数重载+默认值,可能会引发冲突
/* void test(){ */
/* cout<<add(1,2)<<endl; */
/* cout<<add(1,2,3)<<endl; */
/* cout<<add(1.5,2.5)<<endl; */
/* cout<<add(1,2.5)<<endl; */
/* cout<<add(1.3333,2)<<endl; */
/* cout<<add(1,2.77)<<endl; */
/* //缺省调用 */
/* ffunc(10,9); */
/* ffunc(2); */
/* ffunc(); */
/* ff(10,9); */
/* ff(10); */
/* cout<<dd(10,10,10)<<endl; */
/* /1* dd(10,10); *1/ */
/* } */
void ff(int x,int y){
cout<<"x="<<x<<"\t\t";
cout<<"y="<<y<<endl;
}//备胎
/* int main(void) */
/* { */
/* test(); */
/* return 0; */
/* } */
cpp
#include <iostream>
using std::cout;
using std::endl;
extern int add(int,int);
extern double add(double,double);
void test0001(){
cout<<add(2,5)<<endl;
cout<<add(2.8989,5.789)<<endl;
}
int main(){
test0001();
return 0;
}
05,简述C++中引用与指针的联系与区别
联系:
1,都有地址的概念
2,引用的底层是靠指针实现的,可以视为一个受限制的指针
区别:
1,引用必须初始化,指针可以不初始化
2,引用不能修改绑定,指针可以
3,在代码层面,对引用本体取地址取到的是变量本体的地址,对指针取址取到的是指针变量的地址
06,什么是函数重载?其实现原理是什么?如何进行C
与C++
的混合编程?
函数重载:C++允许函数名相同,参数类型、数量不同的函数在同一作用域同时出现
实现原理:名字改编(函数名称相同的时候,会根据参数的类型、顺序、个数进行改编,改变之后的函数名与函数信息相关
混合编程:extern "C" {}
07,什么是inline
函数?inline
与带参数的宏定义之间的区别是什么?
1,在函数最前面有inline关键字的声明函数
加上关键字,就是对编译器提出了内联的建议,如果建议通过,进行内联展开(即用用函数定义体 替代函数调用语句,该行为发生在编译阶段而非程序运行阶段
2,
宏函数: 优点(没有函数开销) 缺点(没有类型检查,安全隐患)
内联函数:不会增加开销,存在类型检查
08,引用作为函数返回值时要注意什么?如果函数返回值是绑定到堆上的变量的引用,应该如何安全地进行使用?
1,确保引用对象的生命周期比函数生命周期长
2,如果是堆上的内存,要避免内存泄漏(使用引用接收函数返回值,可以安全的访问堆上的变量,避免重复申请导致的内存泄露)
cpp
// 错误:返回局部变量的引用
int& getLocalValue() {
int localValue = 10;
return localValue; // localValue 的生命周期结束后,引用变成悬空引用
}
// 正确:返回堆上分配的对象的引用
int* getHeapValue() {
int* heapValue = new int(10);
return heapValue; // 调用者负责释放内存
}
int main() {
int* value = getHeapValue();
// 使用 value
delete value; // 释放内存
return 0;
}