C++回顾 day1

cout格式化输出

cpp 复制代码
cout << setiosflags(ios::left) << setw(8) << a << endl;

重载:名字相同,意义不同

函数名相同,参数列表不同(类型,个数,顺序) 返回值类型不构成重载

先严格进行匹配,匹配到则执行对应算法

再隐式转换寻求匹配,匹配到则执行对应算法

隐式转换:C++允许将较小范围的类型自动转化为较大范围的类型(如int到long、double),或者将数值类型转换为bool类型

注意:函数重载时要避免二义性,比如double可以转flout也可以转int,就会出现二义性(包括像int转long和double)

ambiguous 二义性

q:我分别试了一下发现float既可以调用double的那个也可以调用int的那个,但是全放开他会选择double,这是为啥呢,为啥没有二义性的问题?

a:当 double 作为参数传递给 print(float) 时,编译器会报错,原因是C++ 进行重载解析时,标准转换分为不同的类别,具有不同的优先级:

提升(Promotion):如 char → int,float → double(优先级最高)。 标准转换(Standard Conversion):如 double → float,double → int(优先级较低)。 用户定义的转换和模板匹配(优先级最低)。 double 既可以转换为 int(截断)也可以转换为 float(精度损失),但这两者都是 标准转换(Standard Conversion),所以编译器无法决定哪一个更合适,导致 二义性错误。

q:还有视频里面说2.1这种小数默认是double类型,但是float和double不都是浮点数吗,只是精度不一样

a:auto a = 3.6; 会将 a 推导为 double 类型。 auto b = 3.6f; 会将 b 推导为 float 类型。

强类型和尽量减少类型推断在很多编程场景下都是非常有益的,它们能帮助我们在 编译时发现错误,提高代码可读性和可维护性,并有可能带来 性能提升 和更好的 工具支持。

重载的底层原理:命名倾轧(name mangling):通过修改函数名来区分参数不同的函数

e.g.

cpp 复制代码
void print(int a)   //比如倾轧成void print_i(int a)
{}
​
void print(char a)  //void print_c(char a)
{}
​
void print(int a,char b)//void print_i_c(int a,char b)
{}
​
void print(char a,int b)//void print_c_i(char a,int b)
{}

运算符重载:

cpp 复制代码
返回值类型 operator运算符(参数列表)
{
    重载实体;
}

默认参数规则:从右向左默认,中间不能跳跃

cpp 复制代码
//合法
int valume(int l,int w = 4,int h = 5)
{
    return l * w * h;
}
​
cout << valume(2) << endl;
cout << valume(3,5) << endl;
cout << valume(1,2,10) << endl;
​
//不合法
int valume(int l = 2,int w,int h = 5)
{
    return l * w * h;
}
​
cout << valume(2,3) << endl;
cout << valume(3,5) << endl;
cout << valume(1,2,10) << endl;

重载和默认参数最好不要同时出现,会导致ambiguous二义性错误

引用语法:原数据类型& 别名 = 原名

引用是一种声明关系(意味着必须初始化)

引用不开辟空间

引用一经声明,不可变更(编译阶段就弄好了)

可以对引用再次引用,结果就是同一个变量具有多个别名

cpp 复制代码
int a;
int& ra = a;//ra为a的引用
int& rr = ra;//rr也为a的引用
int& rrr = rr;//rrr还是a的引用
//等价于
int a;
int& ra = a;
int& rr = a;
int& rrr = a;

q:char *p = "askjank"是如何实现p储存字符串的?

a:在C++(以及C语言)中,字符串字面量(如 "askjank")通常存储在程序的只读数据段中。当你声明一个字符指针 char *p = "askjank"; 时,p 被初始化为指向这个字符串字面量的首字符的地址。

字符指针的初始化:char *p 声明了一个字符指针 p。当你将字符串字面量赋值给 p 时(实际上是将字符串字面量的地址赋值给 p),p 就指向了这个字符串的首字符 'a'

q:那cout << *p << endl;会是什么结果?

a:p 是一个字符指针,它指向字符串字面量 "askjank" 的首字符 'a'

q:那我输出p是啥结果?

在C++中,当你有一个字符指针 p 指向一个字符串(无论是字面量还是动态分配的内存中的字符串)时,直接输出指针 p(而不是解引用指针 *p)通常会得到该指针所指向的内存地址的十六进制表示。但是,如果你尝试直接输出一个指向字符串字面量的指针,并且你的编译器和环境支持将指针指向的字符串字面量直接作为字符串输出(这是许多C++编译器和标准库实现的一个常见但非强制的行为),那么输出可能会是字符串本身而不是地址。

然而,根据C++标准,直接输出一个字符指针应该输出指针的值(即地址),而不是它指向的字符串内容。但在实践中,许多编译器允许这种"偷懒"的写法,并会输出字符串内容,特别是当使用 std::cout 时。这种行为是编译器特定的,并且可能因编译器版本和设置而异。

为了明确起见,这里有两种可能的情况:

  1. 按照标准行为

    cpp 复制代码
    char *p = "askjank";
    std::cout << p << std::endl; // 可能输出指针的地址(十六进制),如 "0x7ffeefbff6f4"
  2. 编译器特定的"偷懒"行为

    cpp 复制代码
    char *p = "askjank";
    std::cout << p << std::endl; // 可能输出字符串内容 "askjank"

运行正常但是有警告,这条警告是在C++编程中遇到的,它表明你试图将一个字符串常量(例如 "hello")赋值给一个字符指针(char*)。在C++中,字符串常量是存储在程序的只读内存区域的,因此尝试通过字符指针修改这些字符串会导致未定义行为。

编译器给出这个警告是因为这种转换是不安全的,它可能会导致程序崩溃或其他不可预测的行为。

修改方法:使用 const char\* 而不是 char\*

相关推荐
java1234_小锋几秒前
说说你对Java里Integer缓存的理解?
java·开发语言
float_六七1 小时前
深入理解DFS:从迷宫探险到动态剪枝的征服之路(C++实现)
c++·深度优先·剪枝
xy_optics1 小时前
matlab的meshgrid
开发语言·matlab
John_ToDebug2 小时前
深入解析 Service Worker 在 Chrome 扩展中的应用
c++·chrome·性能优化
一问三不知_3 小时前
pyqt5报错:qt.qpa.plugin: Could not find the Qt platform plugin “xcb“(已解决)
开发语言·python·qt·ubuntu·conda·bug
小白的高手之路3 小时前
Pytorch中的数据加载
开发语言·人工智能·pytorch·python·深度学习·机器学习
ok0603 小时前
JavaScript(JS)单线程影响速度
开发语言·javascript·ecmascript
液态不合群3 小时前
C# 中比较实用的关键字,基础高频面试题!
开发语言·c#
饼干帅成渣4 小时前
我又又又又又又又又更新了~~~纯手工编写C++画图,有注释~~~~~~
开发语言·c++
菜萝卜子4 小时前
【Go 】Go 语言中的 channel介绍
开发语言·后端·golang