《深入应用C++11》第一章

1,using可重定义一个模板,该模板既不是类模板也不是函数模板,是一种新的模板形式:模板别名

templte <typename T>
using func_t=void (*)(T,T);
//使用func_t模板
func_t<int> xxx_2;

2,函数模板的参数在使用上与其他默认函数略不同,它没有必须写在参数表最后的限制。

template <typename R = int , typename U>
R func(U val)
{
val;
}
int main(void)
{
func(123);
return 0;
}

但在调用函数模板的时候,若显示指定了模板的参数,由于参数填充顺序是从左到右的,因此下面这样 调用函数模板返回的是long,不是int
func(123); //func的返回值类型是long

3,当默认模板参数和模板参数自动推导同时使用时,若函数模板无法自动推导出参数类型,则编译器将使用默认模板参数;否则将使用自动推导出的参数类型。
优先级:自动推导出的参数类型 > 默认模板参数

4,POD类型
粗略上来讲,POD是C++为兼容C的内存布局而设计的,主要用于修饰用户自定义类型。
但POD却远比这个要复杂。POD(Plain Old Data),从字面意思上来看,是平凡普通的老旧格式的数据,POD是一个类型属性,既不是关键字也不会像”volatile”用来修饰类型信息。
POD类型,说明该数据是普通的,不会有什么虚函数啊,虚继承啊,或者内嵌的数据类型很复杂的情况。也就是说,POD类型的C++变量,可以直接用C语言中的struct来解释
直观的来说,POD类型中的O代表了与C语言的兼容性,可以直接使用memcpy()直接复制而不会出现任何问题。POD这个想法的由来就是要支持两种最基本的属性:
(1)支持静态初始化
(2)编译C++中的POD类型所得到的内存布局,和C中编译struct的内存布局相同

具体地,C++11将POD类型划分为两个概念:
trivial
standard layout
在C++11中,更多的是用trivial和standard类代替POD类型。

trivial意思是无意义,这个trivial和non-trivial是对类的四种函数来说的:
构造函数(ctor)
复制构造函数(copy)
赋值函数(assignment)
析构函数(dtor)
如果至少满足下面3条里的一条:
显式(explict)定义了这四种函数。
类里有非静态非POD的数据成员。
有基类。
那么上面的四种函数是non-trivial函数

5,在使用初始化列表时,什么样的类型C++会认为它是一个聚合体
(1)类型是一个普通数组
(2)类型是一个类,且

无用户自定义的构造函数
无私有或者保护的非静态数据成员
无基类
无虚函数
不能有{}和=直接初始化的非静态数据成员
聚合类型的定义并非递归的,当一个类的非静态成员是非聚合类型时,这个类也有可能是聚合类型,可以列表初始化。

6,std::initializer_list拥有与一个无参数的构造函数;同时它是非常高效的,它只保存列表中的数据的引用。因此下面的做法是错误的:

std::initializer_list<int> func()
{
int a =1,b=2;
return {a,b};
}

这样虽然可以通过编译,但是无法得到希望的结果,a,b的生命周期在调用后结束,引用的将是不确定的内容。
可以改为:

std::vector<int> func()
{
int a =1,b=2;
return {a,b};
}

7,列表初始化对于类型收窄会报错

8,可调用对象
(1)函数指针
(2)具有operator()成员函数的类对象
(3)一个可被转为函数指针的类对象
(4)一个类成员指针
可调用类型的定义不包括函数类型或者函数引用(只有函数指针),因为函数类型不能直接用来定义对象;而函数引用从某种意义上来说可以看做是一个const的函数指针。

9,std::function是可调用对象的包装器。它是一个类模板,可以容纳除了类成员(函数)指针之外的所有可调用对象。

10,std::bind的返回类型是一个stl内部定义的仿函数类型,可以直接赋值给一个std::function

auto newCallable=bind(callable.arg_list)
newCallable本身是一个可调用对象

例子:

#include <iostream>
#include <functional>

void output(int x,int y){
    std::cout<<x<<" "<<y<<std::endl;
}

int main(int argc, char **argv) {
    std::bind(output,1,2)();// 输出1 2
    //等价于
    auto f=std::bind(output,std::placeholders::_1,std::placeholders::_2);
    f(1,2); //输出1 2
    //等价于
    std::bind(output,std::placeholders::_1,std::placeholders::_2)(1,2);// 输出1 2

    std::bind(output,std::placeholders::_1,2)(1); //输出 1 2
    std::bind(output,2,std::placeholders::_1)(1); //输出2 1
    //std::bind(output,2,std::placeholders::_2)(1); //error 调用时没有第二个参数
    std::bind(output,2,std::placeholders::_2)(1,2); //输出 2 2
    std::bind(output,std::placeholders::_2,std::placeholders::_1)(1,2); //输出 2 1
}

结果:

1 2
1 2
1 2
1 2
2 1
2 2
2 1

11,关于std::bind的一些用法总结
最近在看《深入应用c++11》的时候遇到了std::bind的一些新用法,之前没有遇到过,这里记录下。通常时候std::bind是与std::function一起结合使用的,std::bind是一个函数模板,而std::function是一个类模板,这个从其源码就可看出

/**
 *  @brief Function template for std::bind.
 *  @ingroup binders
 */
template<typename _Func, typename... _BoundArgs>
  inline typename
  _Bind_helper<__is_socketlike<_Func>::value, _Func, _BoundArgs...>::type
  bind(_Func&& __f, _BoundArgs&&... __args)
  {
    typedef _Bind_helper<false, _Func, _BoundArgs...> __helper_type;
    typedef typename __helper_type::__maybe_type __maybe_type;
    typedef typename __helper_type::type __result_type;
    return __result_type(__maybe_type::__do_wrap(std::forward<_Func>(__f)),
             std::forward<_BoundArgs>(__args)...);
  }

template<typename _Signature>
    class function;

std::bind的常见用法
之前的理解仅仅是将bind当做绑定一个全局函数,现在又遇到了一些其他的用法,直接上代码吧

/*
 * main.cpp
 *
 *  Created on: 2017年12月3日
 *      Author: Administrator
 */
#include  <iostream>
#include <functional>

void output(int x, int y)
{
    std::cout << x << " " << y << std::endl;
}
class A
{
public:
    int i_ = 0;

    void output(int x, int y)
    {
        std::cout << x << " " << y << std::endl;
    }

    void operator()() const //无参数 无返回值的仿函数
    {
        std::cout <<"仿函数"<< std::endl;
    }
};

int main(void)
{
    //1,绑定全局函数
    std::bind(output,1,2); //全局函数,仅仅是绑定,没有调用
    std::bind(output,1,2)();//绑定并调用全局函数

    //2,绑定成员函数
    A a;
    std::function<void(int, int)> fr =
        std::bind(&A::output, &a /*调用者*/, std::placeholders::_1, std::placeholders::_2);
    fr(1, 2);  //输出 1 2

    //3,绑定成员变量(包括静态的成员变量) 成员变量这里function中是int&(void)
    std::function<int&(void)> fr_i = std::bind(&A::i_, &a/*调用者*/);  //vs13的bug,绑定成员变量要报错
    fr_i() = 123;

    std::cout << a.i_ << std::endl;  //输出 123
    std::cout << fr_i() << std::endl;  //输出 123

    A a1;
    std::function<int&(void)> fr_i_1 = std::bind(&A::i_, a1/*调用者*/); //调用者没有传指针
    fr_i_1() = 123;

    std::cout << a1.i_ << std::endl;  //输出 0
    std::cout << fr_i_1() << std::endl;  //输出 123

    //4,仿函数
    std::function<void(void)> op = std::bind(&A::operator(),a);
    op();

    return 0;
}

结果如下:

1 2
1 2
123
123
0
123
仿函数

12,lambda表达式通过捕获列表捕获一定范围内的变量

[]不捕获任何变量
[&]捕获外部作用域中所有变量,并作为引用在函数体内引用
[=]捕获外部作用域中所有变量,按值捕获
[=,&foo]按值捕获外部作用域的所有变量,并按引用捕获foo变量
[bar] 仅仅只值捕获bar变量
[this]捕获当前类中的this指针,让lambda表达式拥有和当前类成员函数同样访问权限。如果已经使用了&或者=,就默认添加此项。
捕获this的目的是可以在lambda中使用当前类的成员函数和成员变量

13,lambda无法修改通过赋值方式捕获的外部变量。
易出错点:lambda的延时调用,注意值捕获与引用捕获的时候,延时调用的区别

14,lambda的类型在c++11中被称为“闭包类型”,可认为其是一个仿函数。

    std::function<int(int)> f1=[](int a){return a;};
    std::function<int(int)> f2=std::bind([](int a){return a;},123);
    std::function<int(void)> f3=std::bind([](int a){return a;},123);

这里函数f2和f3都是绑定的同一个函数,但是f2却是带有int参数,f3无参数

15,没有捕获变量的lambda表达式可以直接转换为函数指针,而捕获变量的lambda表达式则不能转换为函数指针。

16,按c++的标准,lambda的operator()默认是const,如果是按值捕获的话,const成员函数是无法修改成员变量的值,而mutable的作用就是取消operator()的const属性。

17,tuple简单的创建与取值方式

    //创建方式1
    tuple<const char*,int> tp=make_tuple("123",1);

    //创建方式2
    int x=1;
    int y=2;
    string s="aa";
    auto tp1=std::tie(x,s,y);//tp的类型实际为std::tuple<int&,string&,int&>

    //取值方式1
    const char * data = tp.get<0>(); //获取第一个值
    int len=tp.get<1>(); //获取第二个值

    //取值方式2
    int x,y;
    string a;
    std::tie(x,a,y) = tp1;
    std::tie(std::ignore,std::ignore,y) =tp1; //只解第三个值

其中std::tie创建的是一个元组的左值引用

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Visual C++集成开发环境是当今最流行的可视化编程工具之一。本书运用大量实例,循序渐进,深入浅出地向读者展示了如何利用Visual C++ 6.0进行用户界面制作,主要讨论了如何处理鼠标、键盘以及计时器消息,如何制作各式各样的菜单、工具条和状态条,如何利用系统预制对话框、定制对话框和属性对话框进行大量数据的交换,以及如何充分利用MFC提供的切分窗口和多视处理文档与视之间数据存储、管理与显示的关系。最后,以一个功能强大可用的例子对本书前面所述的用户界面制作技术进行综合应用。 总之,本书内容全面,思路清晰,是计算机开发人员、有关大专院校师生学习Visual C++不可多得的参考书。 目录 第一章 Visual C++ 6.0概述 1.1 Visual C++ 6.0的特性简介 1.2 Visual C++ 6.0的软、硬件配置要求 1.3 Visual C++ 6.0的安装 第二章 Visual C++ 6.0开发环境 2.1 Visual C++ 6.0主窗口 2.2 Visual C++ 6.0菜单栏 2.3 Visual C++ 6.0工具条 2.4 项目与项目工作区 2.5 资源与资源编辑器 2.6 本章小结 第三章 “Hello World”应用程序 3.1 应用程序的框架 3.2 应用框架示例 3.3 MFC库消息映射 3.4 “Hello World”应用程序 3.5 本章小结 第四章 图形设备接口(GDI) 4.1 设备描述表 4.2 GDI对象 4.3 绘制基本图形 4.4 GDI的示例程序 4.5 本章小结 第五章 鼠标、键盘及计时器 5.1 鼠标 5.2 键盘 5.3 计时器 5.4 本章小结 第六章 菜单 6.1 概述 6.2 普通下拉菜单 6.3 上下文菜单 6.4 改变菜单的显示状态 6.5 动态地增、删和修改菜单项 6.6 菜单间的切换 6.7 本章小结 第七章 工具条 7.1 概述 7.2 制作普通的工具条 7.3 制作高级工具条 7.4 本章小结 第八章 状态条 8.1 概述 8.2 创建一个普通的状态条 8.3 创建一个高级的状态条 8.4 本章小结 第九章 对话框 9.1 概述 9.2 系统预制对话框的制作 9.3 普通对话框的制作 9.4 高级对话框的制作 9.5 无模式对话框的制作 9.6 属性对话框的制作 9.7 对话框条 9.8 基于对话框的应用程序 9.9 本章小结 第十章 切分窗口与多视 10.1 切分窗口 …… 第十一章 文档与视的分离 第十二章 一个小型的绘图系统 附录 二维图形的几何变换 CD-ROM的内容
### 回答1: 《C Primer第五版》是一本经典的C语言教材,旨在为读者提供学习和掌握C语言的基础知识,深入了解C语言的语法和特性,以及如何在C语言中开发程序。整本书分为三个部分,分别介绍C语言基础知识、控制语句和函数,以及数组、指针和字符串等高级主题。其中,基础知识部分讲述了C语言基本的语法和数据类型,详细介绍了变量、表达式、运算符、流控制和函数的定义和调用。控制语句和函数部分深入讨论了C语言中的分支结构、循环结构和函数的定义和使用。高级主题部分介绍了C语言中的数组、指针、字符串和结构体等高级数据类型,并讲述了如何利用这些特性开发高效的程序。另外,本书还提供了大量的示例代码和练习题,帮助读者更好地理解和掌握C语言的编程技巧。此外,《C Primer第五版》的电子书版本具有兼容性强、文字清晰、便于查询等优点,是学习和使用C语言的优秀参考资料。总之,这本书对于想要学习C语言的人来说是一本非常好的入门教材,可以帮助读者在学习C语言过程中更加深入地理解和应用C语言。 ### 回答2: 《C Primer第五版》是一本介绍C语言基础概念的经典电子书。本书共分为18章,全面介绍了C语言的基本语法、控制流、数据类型、函数、指针、数组、字符串、结构体、文件I/O等内容。 本书内容详实,通俗易懂,适合C语言初学者阅读。每个章节都附有大量的示例代码、习题以及解答,加深了读者对C语言概念的理解和掌握。 此外,本书的编排合理,从基础到深入,逐步引入C语言的各个概念,让读者能够逐步掌握C语言编程的基本方法和技巧。作者还通过大量的实例来说明不同技术之间的联系和区别,为初学者提供了实用的学习经验。 总之,《C Primer第五版》是一本非常优秀的C语言入门选手,它不仅适合初学者,也适合具有一定编程经验的读者进行巩固和提高。此外,电子书形式更加便于读者学习和查阅,建议广大读者尝试阅读。 ### 回答3: 《C Primer第五版》是一本针对初学者而编写的C语言教材,由Lippman、Lajoie和Moo合著。本书全面讲解了C语言的基础知识和开发技巧,并以简洁明了的语言、清晰的示例代码和丰富的练习题为特点。这本书可以帮助读者快速成为一个合格的C语言程序员。 本书分为三部分,分别介绍了C语言的基本结构、C语言程序设计和高级C语言编程。第一部分主要讲解了C语言的语法规则、数据类型、变量、运算符等基础知识。第二部分主要讲解了程序设计中的控制结构、数组、函数、指针等内容,包括如何进行模块化设计、如何组织代码、如何调试程序等。第三部分主要讲解了一些高级编程技术,如结构体、链表、文件处理等内容,此外还介绍了C++和C语言库函数的使用。 《C Primer第五版》的优点不仅在于其全面性和丰富性,更在于它注重实践教学。本书在讲解知识点的同时提供了大量的示例程序,并在每章末都有大量练习题供读者练习。这样的设计可以帮助读者更深刻地理解和运用各种知识点,并且能够更快速地掌握C语言的编程技巧和实践经验。 总之,如果你想学习C语言或者提高自己的C语言编程能力,那么《C Primer第五版》绝对是一本不可多得的教材,它可以帮助你轻松地掌握这门语言并成为一个合格的C语言程序员。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值