C++新特性(1)

字符串原始字面量

​ c++11中添加了字符串的原始字面量,定义方式为

R"注释(字符串)注释"

​ ()两边的字符除按可以省略,程序会直接打印括号中的字符串,不会在乎类似转移字符之类。

如下面的代码

	string path1 = "\root\tmp\hello.cpp";
	string path2 = "\\root\\tmp\\hello.cpp";
	string path3= R"(\root\tmp\hello.cpp)";
	cout << "path1:" << path1 << endl;
	cout << "path2:" << path2 << endl;
	cout << "path3:" << path3 << endl;

运行结果

ooth1: mphello.cpp
path2:\root\tmp\hello.cpp
path3:\root\tmp\hello.cpp

​ 可能会奇怪,path1字符串输出的是什么?为什么明明是想输出path1结果输出了ooth1?原因是但斜杠与一些字母代表转义字符,\r表示回到当前行的行首,而不会换到下一行,如果接着输出的话,本行以前的内容会被逐一覆盖,\t是制表符,相当于按下一次tab键,即将”path1:“被"(\r)oot(\t) "替换,导致出现运行结果中的现象。这种现象的解决可以像path2那种写法,出现反斜杠时在加一个反斜杠;或者像path3那种写法处理。

​ 另外一种功能是使用了字符串的原始字面量后,字符串可以占用多行了,代码的可读性得到了改善。

	string str = R"(
		我等了三年,
	就是要等一个机会,
	我要争一口气,
	不是证明我了不起,
	我是要告诉大家,
	我曾经失去的我一定要拿回来
		)";

long long 类型

​ long long实际上与 signed long long, long long int, signed long long int 是一回事。unsigned long long 实际上即为 unsigned long long int。在使用long long类型时,要在数据后添加LL后缀;unsigened long long后添加ULL后缀。

​ 使用宏定义LLONG_MAX,LLong_MIN,ULLONG_MAX,分别可以表示long long数据类型的最大最小值,unsigned long long类型的最大值。

	cout << "long long max:  " << LLONG_MAX << endl;
	cout << "long long min:  " << LLONG_MIN << endl;
	cout << "unsigned long long min:  " << ULLONG_MAX << endl;

运行结果

long long max: 9223372036854775807
long long min: -9223372036854775808
unsigned long long min: 18446744073709551615

类成员变量的快速初始化

​ 在C++98中支持"就地声明"初始化类中的静态成员常量,即通过等号=赋予初始值,非静态成员变量的初始化必须在构造函数中声明。非const static则需要在类外初始化。但在C++11中,可以通过就地方式来实现非静态变量的初始化。但设想一下,如果一个类内都定义了就地初始化和构造函数声明初始化,最后一个执行的是谁呢?

#include<iostream>
#include<string>
using namespace std;
class Person {
public:
	Person():b1("构造函数声明初始化") {};//构造函数声明初始化
	//static int a = 20;//错误,非常量的静态变量必须在类外定义
	string b1 = "就地初始化";//就地初始化
	string b2{"另一种就地初始化方式"};//就地初始化
	//int b2( 1 );//错误的初始化方式
	const static char c = 'c';//静态常量可以在类内定义
};
void main() {
	Person p1;
	cout << p1.b1 << endl;
}

运行结果

构造函数声明初始化

​ 可以看出,字符串变量b1保留的是构造函数声明初始化的值,所以编译器是先进行就地初始化,再进行构造函数声明初始化。

final和override关键字的使用

  • final

    final放在类或虚函数的后面,限制某个类不能被继承或虚函数不能被重写。注意,修饰函数时只能修饰虚函数。

class Animal {
public:
	virtual void shout() {
		cout << "Animal class" << endl;
	}
};//一般不会在基类虚函数中添加final
class Cat final:public Animal {		//Cat类不能再被继承
public:
	void shout()final {				//虚函数不能在被重写
		cout << "cat class" << endl;
	}
};
  • override

​ C++11新标准中提供override关键字来说明派生类中的虚函数。主要的用途是便于在调试的时候发现派生类同名函数的写错,因为这种情况在调试中是非常难发现的,并且是程序员的意图更加清晰。但如果用override标记了未覆盖已存在的虚函数,编译器将会报错。

class Animal {
public:
		virtual void shout() {
		cout << "Animal class" << endl;
	}
};
class Cat:public Animal{
public:
	void shout() override{
		cout << "cat class" << endl;
	}
};

静态断言

​ C++11提供了静态断言, 相比assert,静态断言不需要包含新的头文件,并且可以输出自己希望的输出信息。

static_assert(sizeof(long) == 4,"当前机子不是64位");
	cout << "当前机子是64位" << endl;

​ 值得一提的是,静态断言中的判定表达式必须要是常量表达式。在VS环境下,程序执行之前便判断出常量表达式的真假,当常量表达式为假时,VS会提示”静态断言失败“。

异常与noexcept

​ noexcept是C++11新增特性,相当于throw(),即不向函数外发送任何异常。

#include <iostream>
using namespace std;
void test1()noexcept(true)//括号中可以添加判定表达式
{
     throw "来自test1的异常";
}
void test2()noexcept
{
    throw "来自test2的异常";
}
void test3()throw()
{
    throw "来自test3的异常";
}
void test4()
{
    throw "来自test4的异常";
}
int main() {
    try {
        //test1();//程序中止
        //test2();//程序中止
        //test3();//程序中止
        test4();
    }
    catch (const char *err) {
        cout << err << endl;
    }
    cout << "main结束" << endl;
}

数值 字符串间的转换

  • 数值->字符串

    #include<string>
    string to_string (int val);
    string to_string (long val);
    string to_string (long long val);
    string to_string (unsigned val);
    string to_string (unsigned long val);
    string to_string (unsigned long long val);
    string to_string (float val);
    string to_string (double val);
    string to_string (long double val);
    
  • 字符串->数值

#include<string>
//str:待转换的字符串
//pos:从第几个字符的下标开始无法继续进行,比如321zangao,pos为3
//base: 待转换字符串的禁止,0为自动检测,注意区分最后转换后的数值为10进制
int       stoi( const std::string& str, std::size_t* pos = 0, int base = 10 );
long      stol( const std::string& str, std::size_t* pos = 0, int base = 10 );
long long stoll( const std::string& str, std::size_t* pos = 0, int base = 10 );

unsigned long      stoul( const std::string& str, std::size_t* pos = 0, int base = 10 );
unsigned long long stoull( const std::string& str, std::size_t* pos = 0, int base = 10 );

float       stof( const std::string& str, std::size_t* pos = 0 );
double      stod( const std::string& str, std::size_t* pos = 0 );
long double stold( const std::string& str, std::size_t* pos = 0 );

代码演示

#include <iostream>
#include <string>
using namespace std;
int main() {
    string str = "2022.6.23newera";
    size_t sz{};
    cout << stoi(str, &sz)<<endl << "转换完成字符个数:" << sz << endl;
    cout << stoi(str, &sz,16)<<endl << "转换完成字符个数:" << sz << endl;//将其中的数值看成16进制进行转换
}

运行结果

2022
转换完成字符个数:4
8226
转换完成字符个数:4

  • 更快的转换方式

​ <sstream> 主要用来进行数据类型转换,由于<sstream> 使用 string 对象来代替字符数组(snprintf 方式),避免了缓冲区溢出的危险;而且,因为传入参数和目标对象的类型会被自动推导出来,所以不存在错误的格式化符号的问题。简单说,相比 C 编程语言库的数据类型转换,<sstream> 更加安全、自动和直接。

#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main() {
    stringstream stream;
    string str = "12345";
    int dig = 12345;
    //设置两个存放结果的变量
    int dig_res;
    string str_res;
    //数2字符串
    stream << str;
    stream >> dig_res;
    cout << "数字转成的字符串:" << dig_res << endl;
    stream.clear();
    //字符串2数
    stream << dig;
    stream >> str_res;
    cout << "字符串转成的数字:" << str_res << endl;
    stream.clear();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值