• c++11笔记


    追踪返回类型:

    就是返回类型后置,

    可用于函数模块,也被广泛用于转发函数(如:可以实现参数和返回类型不同时的转发)中,还可用在函数指针、函数引用中;

    类型安全:

    宏的弱点:在于其定义的只是在预处理阶段的名字

    枚举类型的缺点:全局可见,对个枚举类型内的枚举值可能会发生冲突,导致编译失败;

    C++98枚举缺点:

    非强类型作用域,允许隐式转换为整型,占用存储空间及符号性不确定

    C++11:枚举类,又称强类型枚举,在enum后面加上class,即可,还可以指定出wchar_t以外的任何整型;

    enum class Type: char { General, Light, Medium, Heavy };

    优点:强作用域,转换限制,可以指定底层类型;

    智能指针

    shared_ptr参与指向内存的引用计数

    weak_ptr不参与,可以通过成员lock指向对象内存,但不拥有该内存。

    unique_prt代替了以前使用auto_ptr的。而shared_ptr以及weak_ptr则可用在用户需要引用计数的地方。

    智能指针能帮助用户进行有效的堆内存管理,但需要显示声明,而完全不用考虑回收指针类型的内存管理方案更讨人喜欢。

    垃圾回收分类

    垃圾是指:把之前使用过,现在不再使用或没有任何指针再指向的内存空间;

    垃圾回收机制是指:将这些“垃圾”收集起来以便再次利用的机制;

    1.基于引用计数的垃圾回收器:

    优点副作用较小(不会有对系统缓存或交换空间造成的冲击),缺点容易形成“环形引用”问题,由于计数带来的额外开销并不小,所以在实用上有一定的限制

    2.基于跟踪处理的垃圾回收器:

    与1相比,被更广泛的应用。基本方法是产生跟踪对象的关系图,然后进行垃圾回收。

    三种算法:标记-清除;标记-整理;标记-拷贝;

    C++与垃圾回收:

    由于通过引用计数不能解决如“环形引用”的问题,如因多线程程序等而引入的内存管理上的困难,程序员可能需要垃圾回收,如第三方C++垃圾回收库-Boehm,但可移植性较差。

    C++11中的“最小垃圾回收支持”,通过语言的约束来保证安全的垃圾回收机制。

    要保证安全的垃圾回收,首先必须知道C/C++语言中什么样的行为可能导致垃圾回收中出现的“不安全”状况。简单来说,不安去源自于C/C++语言对指针的“放纵”,即允许过分灵活的使用。当发生指针进行自加或自减操作,或指针被异或覆盖再恢复时,会触发垃圾回收。

    定义了“安全”(或称安全派发)指针的操作(即安全派发操作):

    1.在解引用基础上的引用,如&*p

    2.定义明确的指针操作:如:p+1

    3.定义明确的指针转换:如:static_cast<void*>(p)

    4.指针和整型之间的reinterpret_cast,如reinterpret_cast<intptr_t>(p)

    intptr_t是C++11中一个可选择实现的类型,其长度等于平台上指针的长度(通过decltype声明)

    异或不是安全派发操作

     pointer_safety get_pointer_safety() noexcept # 查询确认编译器是否支持最小垃圾回收

    声明该指针所指的内存为“可到达”的:

    void declare_reachable(void* p);

    template<class T> T *undeclare_reachable(T *p) noexcept;

    declare_reachable和undeclare_reachable只是确立了一个代码范围,即两者之间的代码运行中,指针对象不会被垃圾回收器回收。

    在一大片连续的堆内存上进行指针式操作,为了让垃圾回收器不关心该区域,可以用如下代码:

    void declare_no_pointers(char* p, size_t n) noexcept;

    void undelcare_no_pointers(char *p, size_t n) noexcept;

    指定的是从p开始的连续n的内存。

    不向后兼容,对于老的代码我们需要限制指针的使用或使用上述两种方式,让一些不安全的指针使用免于垃圾回收器的检查。

    仅限于在new操作符分配的内存,而malloc分配的内存则被认为总是可达的。因此,有malloc等较老代码的堆内存还是必须由程序员自己控制。

    显示的delete使用与垃圾回收并不会形成冲突,可以保证代码最大可能性的向前兼容(面向未来)。

    理想情况下,程序员应该总是在栈上分配变量,这样变量能够有效地自动释放。

        std::tuple<int, char, std::string> a(std::make_tuple(1,'H', "Hello"));
        int n = std::get<0>(a);
        char c = std::get<1>(a);
        std::string d = std::get<2>(a);

    变长模板函数远强于变长函数,因为变长模板函数不会丢失参数的类型信息,示例代码如下:

    void Printf(const char *s) {
        while(*s) {
            if (*s == '%' && *++s != '%') 
                throw std::runtime_error("invalid format string: missing arguments");
            std::cout << *s++;
        }
    }
    
    template<typename T, typename... Args>
    void Printf(const char* s, T value, Args... args) {
        while(*s) {
            if (*s == '%' && *++s != '%')  {
                std::cout << value;
                return Printf(++s, args...);
            }
            std::cout << *s++;
        }
        throw std::runtime_error("extra arguments provided to Printf");
    }
    
     Printf("hello %s
    ", std::string("world").c_str());
  • 相关阅读:
    jquery 实现 点击按钮后倒计时效果,多用于实现发送手机验证码、邮箱验证码
    javascript 中的后退和前进到上下一页
    文件IO流完成文件的复制(复杂版本主要用来演示各种流的用途,不是最佳复制方案哦)
    int ,Intege,String 三者之间的转换
    servlet生成验证码代码
    jsp servlet 的 请求转发和重定向
    struts2
    SQL连接:内连接、外连接、交叉连接。
    今天参加了聚思力面试
    进程(Process)和线程(Thread)的关系和区别
  • 原文地址:https://www.cnblogs.com/gwzz/p/14688302.html
Copyright © 2020-2023  润新知