一,C++11引入列表初始化来禁止缩窄(长度数据类型强转小长度类型引起的数据丢失)。可将用于初始化的变量或值放到大括号{}内:
int largeNum = 500000; short anotherNum{largeNum }; // error! Amend types int anotherNum{largeNum}; // OK! float someFloat{largeNum}; // error! An int may be narrowed float someFloat{500000}; //OK! 500000 can be accomodated
二,C++11引入了固定宽度的整形,能够以位为单位指定整数的宽度。这些类型为int8_t和uint8_t,分别用于存储8位的有符号和无符号整数。还可以使用16位、32位和64位整型,分别是int16_t、uint16_t、int32_t、uint32_t、int64_t和uint_64_t。要使用这些类型,比如包含头文件<cstdint>。
三,使用八进制或二进制字面常量赋值:
int someNumber = 012; // 八进制12赋值到十进制整型变量; int someNumber = 0b1010; // 二进制1010赋值都十进制整型变量;
四,使用constexpr定义常量表达式:
通过关键字constexpr可以让常量声明像函数:
constexpr double GetPI() {return 22.0/7;}
在一个常量表达式中,可以使用另外一个常量表达式:
constexpr double TwicePI() {return 2*GetPI();}
常量表达式看起来像函数,但在编译器和应用程序来看,它们提供了优化可能性。只要编译器能够从常量表达式中计算出常量,就可以在语句和表达式中对可使用常量的地方使用它。
常量表达式必须包含简单的实现并返回简单的类型。如整型、双精度浮点数等。在C++14中,常量表达式可包含决策结构,如if和switch语句。
使用constexpr并不一定能够保证会进行编译阶段优化,比如,使用常量表达式来计算用户输入数字的两倍,由于编译器无法计算这种表达式的结果,则可能会忽略constexpr,进而将常量表达式视为常规函数进行编译。
可以使用constexpr来将类的构造函数定义为常量表达式,可能有助于提高性能:
class Sample { const char* someString; public: constexpr Sample(const char* input) :someString(input) { // constructor code } };
五,字符串结束字符'\0',它告诉编译器,字符串到此结束。这种C风格字符串是特殊的字符数组,因为总是在最后一个字符加上空字符'\0'。而在代码中使用字符串字面量时,编译器将负责在它后面添加'\0'。
在数组中间插入'\0'并不会改变数组长度,而只会导致将该数组作为字符串处理时,将到这个位置结束。
'\0'看起来像两个字符,但反斜杠是编译器能够理解的特殊转移编码,\0标识空,即它让编译插入空字符或零。不能将其写成'0',因为它标识字符0,其ASCII编码为48。
六,inline关键字
在C/C++中,为了解决一些频繁调用小函数而大量消耗栈空间(栈内存)的问题,特别引入了inline修饰符,表示内联函数。栈空间就是指放置程序的局部数据(函数内数据)的空间。在系统下,栈空间是有限的,假如频繁大量使用就会造成栈空间不足而导致程序出错的问题。
#include <stdio.h> //函数定义为inline即:内联函数 inline char* dbtest(int a) { return (i % 2 > 0) ? "奇" : "偶"; } int main() { int i = 0; for (i=1; i < 100; i++) { printf("i:%d 奇偶性:%s /n", i, dbtest(i)); } }
上面的例子就是标准的内联函数用法,使用inline修饰带来的好处,我们表面上看不出来。其实,在内部的工作就是在每个for循环调用dbtest(i)的地方都换成(i % 2 > 0) ? "奇" : "偶",这样就避免了频繁调用函数对栈内存重复开辟所带来的消耗。
1)inline使用限制:只适合函数内代码简单的函数使用,不能包含复杂的结构控制语句while/switch等,并且内联函数本身,不能是直接递归函数。
2)inline仅是对编译器的建议,最后能否真正内联,看编译器的意思;
3)linline函数的定义放在头文件中,因为内联函数要在调用点展开,编译器必须随处可见内联函数的定义。
4)类中的成员函数与inline
定义在类中的成员函数缺省是内联的,即在类定义时就给出函数定义。否则就不是内联的。
class A { public:void Foo(int x, int y) { } // 自动地成为内联函数 }
如果成员函数的定义体不在类声明中,则需要单独声明:
// 头文件 class A { public: void Foo(int x, int y); }
// 定义文件 inline void A::Foo(int x, int y){}
注意inline必须和定义体在一起才能声明为内联函数:
inline void Foo(int x, int y); // inline 仅与函数声明放在一起,不是内联函数 void Foo(int x, int y){}
void Foo(int x, int y); inline void Foo(int x, int y) {} // inline 与函数定义体放在一起,是内联函数
5)慎用inline:内联能提高函数的执行效率,但是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率,同时消耗更多的内存空间。以下情况不宜使用内联:
a)如果函数体内的代码较长,使用内联将导致内存消耗代价较高;
b)如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。
6)类的构造函数和析构函数容易让人误解呈使用内联函数更有效。要当心构造函数和析构函数可能会隐藏一些行为,如“偷偷地”执行基类或成员对象的构造函数和析构函数,所以不要随便将构造函数和析构函数的定义体放在类声明中。
七,lambda函数:
[optional parameters](parameter list) {statements;}
八,组块分隔符:C++14新增,可提高代码可读性。
int moneyInBank=-70'000; // -70000 long populationChange = -85'000; // -85000 long long countryGDPChange = -70'000'000'000; // -70000000000 double pi = 3.141'592'653'59; // 3.14159265359
九,指针声明:通常将指针声明为指向特定的类型,如int,意味着指针包含的地址对饮的内存单元,存储了一个整数。也可以将指针声明为一个内存块,这种指针被称为void指针。
PointedType *PointerVariableName;
与大多数变量一样,除非对指针进行初始化,否则它包含的值将是随机的。如果不希望访问随机的内存地址,可将指针初始化为NULL。NULL是一个可以检查的值,且不会是内存地址:
PointedType *PointerVariableName = NULL; // initializing value
使用引用运算符(&)获取变量的地址,如果varName是一个变量,&varName将是存储该变量的内存地址。可以使用指针来存储地址:
Type VariableName = InitialValue; // 声明一个变量 Type *Pointer = &Variable; // 声明一个该变量类型的指针,指向该变量的内存地址
解除引用运算符(*)用于访问指针指向内存地址的数据。也叫间接运算符。
int age = 10; int *p = &age; // p指向age的内存地址 cout << *p ; // 输出10 *p = 20; cout << age; // 输出20 memset(&age, 5, 1); cout << age; // 输出5 memset(p, 15, 1); cout << age; // 输出15
十,关于sizeof():
1)用于变量时,输出该变量类型的字节数长度;
2)用于指针时,取决于编译器与操作系统。同一种指针的变量类型,不同操作系统下sizeof的长度不同。
3)用于类/类对象时,指出类声明中所有数据属性占用的总内存量,单位为字节。可能会对某些属性进行填充,也可能不会,取决于编译器。但不考虑成员函数及其内部的局部变量。
4)用于结构体时,指出结构体中所有数据属性占用的总内存量,单位为字节。
5)用于共用体时,指出共用体最大成员的长度,即便该成员并不处于活动状态,单位为字节。
十一,动态内存分配和释放
int myNum[100]; // 静态数组,不用手动释放,退出函数块时自动释放
使用new和delete在自由存储区动态分配和释放内存:
Type *Pointer = new Type; // 分配内存 delete Pointer; // 释放内存 Type *Pointer = new Type[numElements]; // 分配内存块给数组 delete[] Pointer; // 释放内存
不能将运算符delete用于任何包含地址的指针,而只能用于new返回的且未使用delete释放的指针。
十二、关键字const用于指针有三种方式:
int* const p;不能修改指针地址,可以修改*p;
const int* p; 不能修改*p,但可以修改指针地址;这种用得最多,避免指针传递时数据被意外修改。
const int* const p;两则都不能修改。
//指针包含的地址是常量,不能修改,但可修改指针指向的数据: int daysInMonth = 30; int* const pDaysInMonth = &daysInMonth; *pDaysInMonth = 31; // OK!Data pointed to can be changed int daysInLunarMonth = 28; pDaysInMonth = &daysInLunarMonth; // Not OK!Cannot change address! //指针指向的数据为常量,不能修改,但可以修改指针包含的地址,即指针可以指向其他地方: int hoursInDay = 24; const int* pointsToInt = &hoursInDay; int monthsInYear = 12; pointsToInt = &monthsInYear; // OK! *pointsToInt = 13; // Not OK!Cannot change data being pointed to int* newPointer = pointsToInt; // Not OK!Cannot assign const to non-const //指针包含的地址以及它指向的值都是常量,不能修改(这种组合最严格): int hoursInDay = 24; const int* const pHoursInDay = &hoursInDay; *pHoursInDay = 25; // Not OK!Cannot change data being pointed to int daysInMonth = 30; pHoursInDay = &daysInMonth; // Not OK!Cannot change address
const char* str; // 与 const int i,没有区别 ,修饰 其所指向的 内存区域 是 只读的,不允许 修改 char * const str; // const 直接修饰 str,即指针变量本身,说明 该指针变量 本身是只读的,但是,其所指向的内存区域还是可以改变的。 char const* str; // 与声明1 本质一致 const char* const str; // 声明1 和声明 2 的 合并,其意义也是 2者的 合并 const char const* str; // 错误的声明。
十三、动态内存分配失败:
1、使用try-catch捕获std::bad_alloc异常:
try{ int* pointsToManyNums = new int[0x1fffffff]; delete[] pointsToManyNums; }catch(std::bad_alloc) { cout << "error.."; }
2,使用new的变种new(nothrow),分配失败不会引发异常,而返回NULL
int* pointsToManyNums = new(nothrow) int[0x1fffffff]; if(pointsToManyNums==NULL) { cout<<"error..."; }else { delete[] pointsToManyNums; }
十三,引用运算符(&),声明引用时需要将其初始化为一个变量,因此引用只是一种访问相应变量的存储数据的方式。
VarType original = Value; VarType& ReferenceVariable = original;
引用使得可以访问相应变量所在的内存单元,从而降低函数调用时参数传递引起的值拷贝,降低内存消耗。
#include "stdafx.h" #include "windows.h" int add(int a) { return a + a; } void addPoint(int* a) { *a = *a + *a; } void addRef(int& a) { a = a + a; } void addPoint(int a, int* out) { *out = a + a; } void addRef(int a, int& out) { out = a + a; } int main() { int num = 10; printf("test add:%d\n", add(num)); // print 20 int* point = # addPoint(point); printf("test addPoint:%d\n", *point); // print 20 num = 10; int& ref = num; addRef(ref); printf("test addRef:%d\n", ref); // print 20 int* out1 = new int; addPoint(10, out1); printf("test addRef:%d\n", *out1); // print 20 delete out1; int ii1 = 0; int& out2 = ii1; addRef(10, out2); printf("test addRef:%d\n", out2); // print 20 int* ii2 = new int; int& out3 = *ii2; addRef(10, *ii2); printf("test addRef:%d\n", *ii2); // print 20 printf("test addRef:%d\n", out3); // print 20 delete ii2; system("pause"); return 0; }
使用const关键字,可以禁止通过引用修改它指向变量的值。且const引用,只能赋值给const引用。
int original = 30; const int& constRef = original; constRef = 40; // Not allowed: constRef can't change value in original int & ref2 = constRef; // Not allowed: ref2 is not const const int& constRef2 = constRef; // OK
相关推荐
C++学习笔记C++学习笔记C++学习笔记C++学习笔记C++学习笔记
C++学习笔记
### C++ 学习笔记精华版 #### 一、C++ 语言概述 **1、历史背景** - **C++ 的江湖地位** - Java、C、C++、Python、C# 是当前主流的编程语言之一,而 C++ 在这些语言中以其高效性和灵活性著称。 - **C++ 之父 ...
1. 关于C和C++语言的互调问题,extern "C"的作用至关重要。它确保了C++代码能够调用C语言编写的函数,而不会产生因为语言规范差异导致的编译错误。C++编译器在处理函数声明时会考虑函数签名(包括参数类型),而C...
《千锋C++笔记》是一份综合性的学习资料,涵盖了C++编程语言的基础到高级概念。这份笔记由知名教育机构“千锋”提供,旨在帮助初学者和有一定基础的程序员深入理解和掌握C++这一强大的系统级编程语言。下面将详细...
6. **C++11及以后的新特性**:C++11引入了许多新特性,如auto关键字、右值引用、lambda表达式、智能指针等,C++14和C++17进一步增强了这些特性,使得C++更加现代化和高效。 7. **内存管理**:理解指针是学习C++的...
- C++11是C++的一个重要更新,引入了如右值引用、lambda表达式、auto类型推断、nullptr等新特性,提升了C++的现代性和易用性。 7. **STL(标准模板库)**: - STL是C++的标准库,包含容器(如vector、list、map等...
"自考C++笔记(上)" 本笔记是作者全部手打创作的自考C++笔记,包含课本中例子的详细分析,共47200字,适合没有学过C语言的人认真学习和通过C++自考。 C++程序设计 ### 认识 C++的对象 #### 1.1 初识 ...
这份笔记主要涵盖了C++的基础知识,包括C++11和C++17的新特性,旨在帮助初学者理解C++的核心概念。 ### C++11特性 1. **引用(Reference)**:引用是一种别名机制,一旦引用被初始化为一个对象后,它就始终绑定到...
"黑马C++学习笔记" 本笔记主要记录了C++的基础知识和一些重要的概念,包括变量的声明、赋值、输出、引用、指针、结构体等。 变量声明和赋值 在C++中,变量的声明和赋值是非常重要的。变量可以是整数、浮点数、...
C++Primer中文第三版(C++从入门到精通)第一章的读书笔记,主要是C++程序、预处理器指示符、iostream库等的基础知识点读书笔记。
这份"C++笔记"包含了学习C++时的重要知识点和实践技巧。 1. **基础语法**:C++的基础包括变量、数据类型(如整型、浮点型、字符型等)、运算符(算术、比较、逻辑、位运算符等)、流程控制语句(如if-else、switch-...
【C++学习笔记】这份详尽的资源是为那些希望深入了解C++编程语言的人们精心准备的。C++是一种强大的、通用的编程语言,它的设计理念是面向对象,同时支持过程化编程,使得它在系统软件、应用软件、游戏开发、设备...
1. C++语言的联邦概念:C++是一个由多个次语言构成的语言联邦,这包括了C语言核心、面向对象的C++、模板C++以及标准模板库(STL)。这种理解对于深入学习C++至关重要。 - C语言核心:C++保留了C语言的语法,如区块...
对于C++而言,常见的开发工具之一便是Microsoft的Visual Studio系列。在本案例中提到的Visual Studio 2010旗舰版是一种较为成熟且功能全面的IDE。为了更好地提升编程体验,通常还会搭配使用一些插件或辅助工具,如...
1. **空头程序**:C++中的空头程序是一个没有实际操作的简单程序,通常用于测试编译环境。例如: ```cpp int main() { return 0; } ``` 2. **Hello World**:这是学习任何编程语言的第一步。在C++中,"Hello,...
【达内C++课程笔记】是一份全面涵盖了C++编程语言以及相关技术的教程资源,由达内科技提供。这份笔记不仅包含C++的基础知识,还深入探讨了C++的高级特性和实际应用,旨在帮助学习者从入门到精通,掌握C++编程技能。 ...
1. 类与对象:C++的核心是面向对象编程,类是对象的蓝图,通过定义类可以封装数据和函数,实现数据隐藏和抽象。文件C++(day03).txt可能详细讲解了类的定义、构造函数、析构函数以及成员函数的使用。 2. 继承与多态...
1. **变量和数据类型**:C++提供了多种数据类型,如int、float、char等,用于存储不同类型的数据。变量是存储数据的容器,每个变量都有特定的类型。 2. **运算符**:C++支持算术运算符(+、-、*、/、%)、关系...
C++ 学习笔记C++ 学习笔记C++ 学习笔记C++ 学习笔记002