专栏首页BrianC++11基础学习系列三

C++11基础学习系列三


概述

随着自己学习C++11的进度,今天记录和实战C++11的战果。废话少说,直接记录C++11的点滴。

数组

在前面学习系列里面,介绍了模板容器类vector,是一个单链表。今天来了解一下C++中的数组。数组也是存放相同类型的容器,数组的大小是固定不变的(编译时数组的维度必须是已知的)。如果想动态操作容器(增加,删除等)或者事先不知道容器的大小,请使用vector。 在使用数组时注意一下几点: 1.数组的维度必须是常量表达式,在编译时是已知的。

#错误的,无法通过非常量表达式初始化数组,请使用constexpr.
unsigned int size = 12;
#正确的
constexpr unsigned int size = 12;
#getsize()返回结果必须是常量表达式。
int a[size/getsize()]={1,2,3};

2.数组的类型不能使用auto关键字推断类型。 3.显示初始化数组元素时,可省略数组的维度。

int a[]={1,2,3};
string b[4]={"a","b"};

4.数组时不允许copy和赋值,不能将数组的内容拷贝给其他数组作为初始值,也不能为其他数组赋值。

int a[]={1,2,3};
// 错误的
int b[] = a;
// 错误的
b=a;

5.指针和数组很多细节需要注意,包括通过指针访问数组元素。比如:

// temp是含有10个整形指针的数组
int *temp[10];
// temp是个指针,指向一个含有10个整数的数组。
int (*temp)[10];
// temp引用一个含有10个整数的数组。
int (&temp)[10];
string nums[]={"a","b"};
// 指向数组的首元素的指针
string *p = nums;
// p1的类型是指针类型,指向的是string*
auto(nums) p1;
// p2 是一个字符串数组
decltype(nums) p2 = {"c","d"};
//C++11引入新的标准,来获得数组的首元素地址和末尾元素的下一个位置的地址。
int nums [] = {2,3,4,5};
int *start = begin(nums);
int *last = end(nums);

显示转换

强制类型显示转换有static_cast,dynamic_cast,const_cast和reinterpret_cast.其中dynamic_cast是运行时识别的一种技术,后面会详细介绍。

  • static_cast:任何具有明确定义的类型转换(不包含底层const),比如:数值类型转换,void* 类型的转换。(const int * const a 其中靠近a的为顶层cast,远离a的为底层cast。) int i,j; double k = static_cast<double>(j)/i; void *p = &i; int *t = static_cast<int*>(p);
  • const_cast智能改变运算对象的底层const,它可以去掉底层const的性质。 const string *p; string *q = const_cast(string*)(p);
  • reinterpret_cast为运算对象的位模式提供较低层次上的重新解释,由于是对象的位模式,所以严重依赖硬件的架构。实际运用较少。

函数

再详细讲解C++11函数对象之前,首先要熟悉看一下局部对象,局部对象包括:自动对象和局部静态对象

函数局部对象

局部对象 形参和函数体内定义的变量,局部变量还会隐藏外层作用域的同名对象。在所有函数体之外定义的对象存在于程序的整个执行过程,当程序启动时被创建,知道程序结束时被创建。

  • 自动对象 存在于块执行期间的对象,形参是一种自动对象。如果变量本身含有初始值,就用这个初始值进行初始化;如果不包含初始值,执行默认初始化,内置类型的默认初始化将产生未定义的值。
  • 局部静态对象 通过static将局部对象定义的,执行第一次经过对象定义的语句时初始化,知道程序结束时销毁,内置类型的局部静态变量初始化为0.

函数参数传递

依据形参传递的类型将函数传递,分为按引用传递和按值传递,当形参为引用类型时是按引用传递,实际是传递实参的别名。当实参的值被拷贝给形参时,形参和实参是两个互相独立的对象,这是按值传递。还有一种是指针形参,指针是按值传递的,当执行指针拷贝时,拷贝的是指针的值。所以你可以通过指针来修改实参的值。 由于拷贝大的类型对象或者容器对象比较低效,甚至有的类型(IO类型)是不支持拷贝的,这时我们尽量采用按引用传递,这样可以避免拷贝付出的代价。如果函数内无须改变参数的值时,最好将其声明为常量引用。

const形参和实参

顶层const作用于对象本身。

// 顶层const对象,不能改变a
const int a = 12;
// 当拷贝a时,忽略了顶层const的影响。
int i = a;
// 顶层const对象,不能改变p的值。
int * const p = &i;
// 但可以通过p所指向的地址修改它的value。
*p=12;

当用实参初始化形参时会忽略掉顶层const,形参的顶层const会被忽略掉。

//func既可以接收int,也可以接收const int,但是不能修改i的值。
void func(const int i);

尽量使用常量引用

可变形参的函数

可变形参是通过initializer_list实现,但是要求类型一致。

#include <iostream>

void message(std::initializer_list<std::string> temp){
    for(auto i:temp){
        std::cout << i << std::endl;
    }
}

int main() {
    message({"hello","world","brian"});
    return 0;
}

返回类型

1.不要返回局部对象的引用或者指针 由于局部对象在函数调用完后,局部对象所占用的存储空间随之被释放。 2.引用返回左值 调用一个返回引用的函数得到左值,其它返回类型为右值。

#include <iostream>
char &get_char(std::string & a,std::string::size_type index) {
    return a[index];
}
int main() {
    std::string s="hello";
    get_char(s,2)='E';
    std::cout <<s<< std::endl;
    return 0;
}
# 输出为
hEllo

3.通过列表初始化返回多个值

#include <iostream>
#include <vector>

std::vector<std::string> get_err(){
    return {"hello","error"};
}

int main() {
    auto list = get_err();
    for(auto i : list){
        std::cout << i << std::endl;
    }
    return 0;
}
#输出为
hello
error

4.返回数组的指针 由于数组不能被拷贝,所以函数不能返回数组,但是可以返回数组的指针或引用。 在C语言中通过typedef来重命名一个类型名称,在C++中通过using来,虽然typedef可以在c++继续使用,但是还是建议使用using.

typedef int arr[10]; //arr是类型别名,表示含有10个整数的数组。
等价于
using arr = int[10];
int (*p2)[10] = &arr; //p2是一个指针指向一个含有10个整数的数组

值得注意的是如果要返回数组指针的函数,稍微麻烦一些: Type(*function(parameter_list))[dimension] int(*func(int i))[10],func是一个函数指针,指向一个返回值为10个整数的数组。 由于这样声明太过于麻烦,所以在c++11标准中通过尾置返回类型,任何函数都能使用尾置返回类型。上述的声明可以通过: auto func(int i)->int(*)[10]

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • C++11基础学习系列一

    ---- 概述 C++11标准越来越趋于稳定和成熟,国外c++11如火如荼而国内却依然处于观望期。每当提到C++很多程序员都很抵触,特别是学术界的呼声更高一些。...

    BrianLv
  • Python进阶教程(三)

    Python 进阶 我们在Python进阶教程(二),介绍了一些Python进阶用法。今天给大家介绍的是和c/c++混合编程的用法。我们都知道特别是Python...

    BrianLv
  • CentOS6 Upgrade Python

    CentOS6 升级Python2.7.X和Python3.X ---- 简述 由于产品需要从裸机开始开发所以所有的配置和开发也是从零开始,这个导航是基于cen...

    BrianLv
  • C/C++里的const(2)

    对于如下几个语句,哪些定义相同?哪些定义不同?哪些数据可修改?哪些数据不可修改呢?

    用户7043923
  • C语言中修改const int 定义的常量()

    真正让我懂了的解释: volatile 指出 i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放...

    柴银磊
  • C语言第三讲,基本数据类型

            C语言第三讲,基本数据类型 一丶基本数据类型讲解 在C语言当中,有四种基本数据类型 分别是: 整形 浮点型 指针 聚合类型(数组和结构) 整型家...

    IBinary
  • C语言函数求参数顺序问题

    对于函数func,先求右边x+=2参数,返回x=8,然后计算结果。也就是传递给形参的两个值都是8,返回值为16。

    用户6755376
  • 指针在数组中的数据传递作用

    用户5166556
  • BZOJ2194: 快速傅立叶之二(NTT,卷积)

    attack
  • 你不知道的Interface的骚操作

    "难道面试不顺利?"小A心想。于是问小呼都问了什么。小呼说,面试官问了个奇怪的问题,

    PhoenixZheng

扫码关注云+社区

领取腾讯云代金券