浅谈C++对于C的特性区别--1

一.定义字符串

C++提供了string类来定义字符串

string的特点:不需要考虑数据越界的问题,虽本质还是字符数组,但他不是以'\0'结尾,而是优化掉了'\0'

1.string在输入输出时的特点:

输出:

string方式:直接输出字符串名

std::string s = "abc";
std::cout << s << std::endl;

字符数组的方式:

占位符:“%s”

char c[] = "abc";
std::cout << c << std::endl;
printf("%s\n", c);

输入:string方式:直接输出字符串名

std::string s = "abc";
std::cin >> s;//无需考虑字符串长度问题

字符数组的方式,直接输入字符数组中(需要考虑数组越界的问题)

char c[] = "abc";
std::cin >> c;//输入字符串长度超过3则会出现错误
scanf("%s", c)

2.字符串长度

字符数组的方式,strlen(字符串函数),不包括‘\0’,返回值就是字符串长度

char c[] = "abc";
std::cout << strlen(c) << std::endl;//3
std::cout << strlen("abcd") << std::endl;//4

string方式:

字符串.length()或者字符串.size() 不包括‘\0’

std::string s = "abc";
std::cout << s.length() << std::endl;//3
std::cout << s.size() << std::endl;//3

数组元素个数表示数组的元素数量(包括'\0')

char c[] = "abc";
std::cout << sizeof(c) << std::endl;//4
char c1[10] = "abc";
std::cout << sizeof(c1) << std::endl;//10
std::string s = "abc";
std::cout << sizeof(s) << std::endl;//40 预留40的长度,长度不够会总动添加

3.字符串的访问

字符数组的访问:

char c[] = "abc";
std::cout << c[1] << std::endl;//b
c[1] = 'q';
std::cout << c << std::endl;

string方式:数组下标访问

std::string s = "abc";
std::cout << s[1] << std::endl;//b

4.字符串的遍历

字符数组的方式:下标循环遍历

char c[] = "abc";
for (int i = 0; i < strlen(c); i++)
{
std::cout << c[i];
}

string的方式:数组下标访问

std::string s = "abc";
for (int i = 0;i < s.length();i++)
{
std::cout << s[i];
}

二.名字空间(命名空间)

std::"标准名字空间(namespace),c++标准库中的所有函数,变量,类型都是在std空间中。 在C++中,命名空间是一个用于封装标识符的容器。通过将相关的标识符放置在命名空间中,可以将它 们从全局命名空间中隔离开来,避免不同部分的代码之间的命名冲突。

名字空间的作用: 避免名字冲突 划分逻辑单元

注:名字空间成员可以是全局变量,函数,名字空间

名字空间的使用:

1. 通过作用域限定操作符 "::"
空间名::要访问的成员;
std::cout << "ns1::num = " << ns1::num << std::endl;
ns1::fun();
ns1::ns2::fun();
2.名字空间指令

using namespace 名字空间名;

在该条指令以后的代码中,指定名字空间中的成员都可见,可以直接访问,省略"空间名::" 常用场景:using namespace std;

#include <iostream>
using namespace std;
namespace ns1
{
   int num;
   void fun()
   {
    cout << "这是ns1的fun函数" << endl;
   }
    namespace ns2
    {
        void fun()
        {
        cout << "这是ns2的fun函数" << endl;
        }
    }
}
int main()
{
    using namespace ns1;
    cout << "num = " << num << endl;
    fun();
    ns2::fun();
return 0;
}
3. 名字空间声明

using 名字空间名::名字空间变量;

将名字空间中特定的一个成员引入当前作用域,在该作用域访问这个成员就如同访问局部的成员一样,可以 直接访问,省略"空间名::"

using ns1::num;
cout << "num = " << num << endl;
using namespace ns1;
fun();
ns2::fun();
4.无名名字空间

不属于任何名字空间的标识符,将被编译器自动的放入无名名字空间中,无名空间里面的成员正常可以直接 访问,但是当无名空间的成员和局部变量的标识符名字一样时,局部优先,这时如果还希望访问无名空间的 成员,可以使用作用域限制操作符:"::要访问的成员"(当然也可省略::)

#include<iostream>
using namespace std;//标准名字空间指令
namespace ns1
{
  int num = 100;
  void func(void)
  {
      cout << "ns1的func函数" << endl;
  }
}
namespace ns2
{
  int num = 200;
  void func(void)
  {
    cout << "ns2的func函数" << endl;
  }
}
//将被放入无名名字空间中
int num = 300;
int main()
{
    cout << num << endl;//300
    using ns1::num;//名字空间声明
    cout << num << endl;//100
    cout << ns2::num << endl;//200
    cout << ::num << endl;//300 无名名字空间
return 0;
}

三.函数重载

如果两个函数名字相同会发生什么?

         定义(C++允许函数重名,但是参数列表要有区分)
在相同的作用域定义同名的函数,但是它们的参数要有所区分,这样的多个函数构成重载关系

#include<iostream>
using namespace std;

void fun(int a)
{
    cout<<"fun(int)"<<endl;
}
void fun(int a,int b){
    cout<<"fun(int,int)"<<endl;
}
void fun(int a,float b){
    cout<<"fun(int,float)"<<endl;
}
int main(){
    fun(1);
    fun(1,2);
    fun(1,2.1f);
return 0;
}

函数重载与返回值无关,下面的例子不能构成重载

#include<iostream>
using namespace std;
void fun(int a)
{
    cout << "fun(int)--void" << endl;
}
int fun(int a)
{
    cout << "fun(int)--int" << endl;
    return a;
}
int main()
{
    fun(1);
    return 0;

}

函数重载匹配

#include<iostream>
using namespace std;
void fun(int a)
{
    cout << "fun(int)" << endl;
}

void fun(int a, int b)
{
    cout << "fun(int, int)" << endl;
}
void fun(int a, float b)
{
    cout << "fun(int, float)" << endl;
}
int main()
{
    fun(1, 1.1);//error
    return 0;
}

调用重载关系的函数时,编译器将根据实参与形参的匹配程度,自动选择最优的版本

当前编译器的一般匹配规则: 完全匹配>=常量匹配>升级转换>降级转换(标准转换)>省略号匹配

C++编译器是通过对函数进行换名,将参数表信息整合到新的名字中,实现解决函数重载和名字冲突的问题

void fun_857(int a, float b)
{
cout << "fun(int, float)" << endl;
}

例如在上述例子中,编译器会将 fun_857 函数整合参数信息重新命名为 fun_857if ,从而实现对函数名 称的区分,但是没有将返回值信息整合,这也就是为什么重载与返回值无关。

四.lambda函数

当前所有的函数都是有一个具体名字的。但C++支持支持匿名函数,即可以不给函数命名。

1.lambda函数的定义

lambda被用来表示一种匿名函数.所谓匿名函数,简单地理解就是没有名称的函数.又常被称为lambda函 数或者lambda表达式。

2.lambda函数的语法

定义:

[外部变量访问方式说明符] (参数) mutable -> 返回值类型

{

        函数体;

};

各部分的含义分别是:

(1)[外部变量访问方式说明符]        

[]方括号用于向编译器表明当前是一个lambda表达式,其不能被省略*。([]里的内容可以省略)

比如,如下就定义了一个最简单的lambda匿名函数: 与普通函数返回值不同,lambda函数返回一个函数对象,所以要auto去捕获他,不能使用it类型 去接收

auto d = [] {};// 一个空的lambda表达式

在方括号内部,可以注明当前lambda函数的函数体中可以使用哪些“外部变量”。所谓外部变量,指的是和 当前lambda表达式位于同一作用域内的所有局部变量。

(2) (参数)

和普通函数的定义一样,lambda匿名函数也可以接收外部传递的多个参数.和普通函数不同的是,如果不需 要传递参数,可以连同()小括号一起省略

auto c = []/*()*/{
    int a = 1;
    int b = 2;
    return a / b;
};
cout << c() << endl;
auto square = [](int x)/* -> int*/ {
    return x;
};
cout << square(1) << endl;

(3)mutable

此关键字可以省略,如果使用则之前的()小括号将不能省略(参数个数可以为0)。默认情况下,对于以值传递 方式引入的外部变量,不允许在lambda表达式内部修改它们的值(可以理解为这部分变量都是const常量). 而如果想修改它们,就必须使用mutable关键字。

注意:对于以值传递方式引入的外部变量,lambda表达式修改的是拷贝的那一份,并不会修改真正的外部 变量

[] 空方括号表示当前lambda匿名函数中不导入任何外部变量.

[=] 只有一个=等号,表示以值传递的方式导入所有外部变量.

auto d = [=](int i) mutable {
    int x = 3;
    int y = 4;
    a = 10;//lambda表达式修改的是拷贝的那一份,并不会修改真正的外部变量
    return a + b + i + x + y;
};
//默认是值传递
auto c = [=](int i) /*-> float*/ {
    int x = 3;
    int y = 4;
    //a = 10;//error 以值传递方式引入的外部变量,不允许在lambda表达式内部修改它们的值
    return a + b + i + x + y;
};
cout << c(5) << endl;
cout << d(5) << endl;

(4)[val1,val2,...] 表示以值传递的方式导入val1,val2等指定的外部变量,

同时多个变量之间没有先后次序

int a = 1;
int b = 2;
int c = 3;

auto d = [a, b](int i) /*-> float*/ {
    int x = 3;
    int y = 4;
    //return a + b + c + i + x + y;//error c没有传入,不能使用
    return a + b + i + x + y;
};

cout << d(5) << endl;

(5)返回值类型

指明lambda匿名函数的返回值类型.大部分情况下可以直接省略 ->返回值 类型(返回一个函数对象)

#include<iostream>
using namespace std;
int main()
{
    auto add = [](int a, int b) -> int
    {
        return a + b;
    };

// 调用lambda表达式并输出结果
int result = add(3, 4);
std::cout << "Result: " << result << std::endl; // 输出 "Result: 7"

return 0;
}

(6)函数体

和普通函数一样,lambda匿名函数包含的内部代码都放置在函数体中.该函数体内除了可以使用指定传递 进来的参数之外,还可以使用指定的外部变量以及全局范围内的所有全局变量。在lambda表达式内可以 使用任意一个全局变量,必要时还可以直接修改它们的值。

全局变量可以修改

#include<iostream>
using namespace std;
double d = 5.0;
int main()
{
    int a = 1;
    auto c = [a]()
    {
        double b = 2.0;
        d = 6.0;
        //a = 2;///error
        double res = d / b;
        return res;
    };

cout << c() << endl;
cout << d << endl;

return 0;
}

  • 15
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值