auto与unordered_map

目录

引入

auto类型

unordered_map无序容器


引入

首先来看一道leetcode上的简单题目


leetcode 409 最长回文串

题目描述

给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。

在构造过程中,请注意区分大小写。比如 "Aa" 不能当做一个回文字符串。

注意:
假设字符串的长度不会超过 1010。

示例 1:

输入:
"abccccdd"

输出:
7

解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。

思路与题解

(复制自leetcode官方)


看懂了思路之后,就该根据思路实现代码了,在官方给出的C++答案中,代码是这样的:

class Solution {
public:
    int longestPalindrome(string s) {
        unordered_map<char, int> count;
        int ans = 0;
        for (char c : s)
            ++count[c];
        for (auto p : count) {
            int v = p.second;
            ans += v / 2 * 2;
            if (v % 2 == 1 and ans % 2 == 0)
                ++ans;
        }
        return ans;
    }
};

在这段代码中,就使用到了两个C++11特性中新增的内容:auto类型说明符无序容器unorder_map

那么这两个内容都有哪些特点与要点呢?


以下内容来自大学课本《C++ Primer》

auto类型

1、为C++11标准中新引入的一个类型说明符,可以让编译器为我们自动分析判断表达式所属的类型。

2、auto让编译器通过初始值来推算变量的类型(这一点类似于Python)。显然,auto定义的变量必须有初始值:

//由val1和val2相加的结果可以推断出item的类型
auto item = val1 + val2;//item初始化为val1和val2相加的结果

3、auto可以在一条语句中声明多个变量。因为一条生命语句只能有一个基本数据类型,所以该语句中所有变量的初始基本数据类型都必须一样。切记,符号&和*只从属于某个声明符,而非基本数据类型的一部分,因此初始值必须使同一种类型。

举几个例子(其中有《C++ Primer》原例)如下:

auto i = 0, *p = &i;//正确,i是整数,p是整形指针
auto sz = 0, pi = 3.14;//错误,sz和pi的类型不一致
auto str = '123', s = '234';//正确,str和s的类型相同
auto a = 123 + 234;//正确,此时a的数据类型为整型

在上述例子中,auto根据第一个表达式来确定整个语句的数据类型。

auto k = ci, &l = i;//k是整数,l是整型的引用
auto &m = ci,*p = &ci;//m是对整型的引用,p是指向整型常量的指针
auto &n = i, *p2= &ci;

上述例子的第三个例子是错误示例,读者朋友们能够看出原因吗?这是一个gif

除此之外,对于size函数来说,由于其返回的是一个string::size_type类型的值,不太容易理解和使用,所以可以使用auto类推断变量的类型:

auto len = line.size();//len的类型是string::size_type;

在我们熟知的for循环中,也可以利用auto,正如给出的题目例子中的for循环:

for (auto p : count) {
      int v = p.second;
      ans += v / 2 * 2;
      if (v % 2 == 1 and ans % 2 == 0)
            ++ans;
}

由于count是一个无序容器unordered_map,所以在对其进行遍历时,可以使用auto来帮我们做这件事,这样倒也省下了不少力气。

auto也不止于此


以下含有大量原文,不喜欢的朋友可以跳过或参照原书


编译器推断出的auto类型有时候和初始值的类型并不完全一样,编译器会适当地改变结果类型使其更符合初始化规则。

首先,使用引用其实是使用引用的对象,特别是当引用被用作初始值时,真正参与初始化的其实是引用对象的值。此时编译器以引用对象的类型作为auto的类型:

int i = 0, &r = i;
auto a = r;//a是一个整数(r是i的别名,而i是一个整数)

其次,auto一般会忽略掉顶层const,同时底层const则会保留下来,比如当初始值是一个指向常量的指针时:

const int ci = i , &cr = ci;
auto b = ci;
auto c = cr;
auto d = &i;
auto e = &ci;
const auto f = ci;

上述声明中,b由于忽略掉了ci的顶层const特性所以是一个整数,c亦然,d是一个整形指针,而e则由于对常量对象取地址所以是一个底层const,从而是一个指向整形常量的指针。

如果我们希望推断出的auto类型是一个顶层const,那么需要明确指出就像f的声明一样。

还可以将引用的类型设为auto,此时原来的初始化规则仍然适用:

auto &g = ci;  //g是一个整型常量引用,绑定到ci
auto &h = 42;  //错误:不能为非常量引用绑定字面值
const auto &j = 42;  //正确:可以为常量引用绑定字面值

设置一个类型为auto的引用是,初始值中的顶层常量属性仍然保留。和往常一样,如果我们给初始值绑定一个引用,则此时的常量就不是顶层常量了。

在使用new来进行动态分配时也可以使用auto:

auto p1 = new auto(obj);

此时,p指向一个与obj类型相同的对象,该对象用obj进行初始化。注意,由于编译器要用初始化器的类型来推断要分配的类型,只有当括号中仅有单一初始化器时才可以使用auto。


unordered_map无序容器

在C++11新标准中一共定义了4个无序关联容器(unordered associative container)。这些容器不是使用比较运算符来组织元素,而是使用哈希函数(Hash Function)关键字类型的==运算符。

4个无序关联容器如下(这个只敲了一半靠编译器提示的屑作者)

这是一个png

由于其名字中带有“无序(unordered)”二字,那么从表面上我们就可以看出来其使用的范围:在某关键字类型的元素没有明显的序关系的情况下。在《C++ Prime》中指出:

如果关键字类型固有就是无序的,或者性能测试发现问题可以用哈希技术解决,就可以使用无序容器

 而在基础操作方面,以此处的unordered_map为例,提供了与map相同的操作,也就是说曾用于map的操作可以用于unordered_map上,而与map唯一的区别,就在于其输出也是无序的。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值