C++11 auto使用及注意事项

  1. auto的用法

    在真正编程的时候也不建议这样来使用auto,直接写出变量的类型更加清晰易懂。下面列举auto关键字的正确用法。

    用于代替冗长复杂、变量使用范围专一的变量声明。

    想象一下在没有auto的时候,我们操作标准库时经常需要这样:

    
    #include<string>
    
    
    #include<vector>
    
    int main()
    {
        std::vector<std::string> vs;
        for (std::vector<std::string>::iterator i = vs.begin(); i != vs.end(); i++)
        {
            //
        }
    }

    这样看代码写代码实在烦得很。有人可能会说为何不直接使用using namespace std,这样代码可以短一点。实际上这不是该建议的方法(C++Primer对此有相关叙述)。使用auto能简化代码:

    
    #include<string>
    
    
    #include<vector>
    
    int main()
    {
        std::vector<std::string> vs;
        for (auto i = vs.begin(); i != vs.end(); i++)
        {
            //..
        }
    }

    for循环中的i将在编译时自动推导其类型,而不用我们显式去定义那长长的一串。

    在定义模板函数时,用于声明依赖模板参数的变量类型。

    template <typename _Tx,typename _Ty>
    void Multiply(_Tx x, _Ty y)
    {
        auto v = x*y;
        std::cout << v;
    }

    若不使用auto变量来声明v,那这个函数就难定义啦,不到编译的时候,谁知道x*y的真正类型是什么呢?

    模板函数依赖于模板参数的返回值

    template <typename _Tx, typename _Ty>
    auto multiply(_Tx x, _Ty y)->decltype(_Tx*_Ty)
    {
        return x*y;
    }

    当模板函数的返回值依赖于模板的参数时,我们依旧无法在编译代码前确定模板参数的类型,故也无从知道返回值的类型,这时我们可以使用auto。格式如上所示。
    decltype操作符用于查询表达式的数据类型,也是C++11标准引入的新的运算符,其目的也是解决泛型编程中有些类型由模板参数决定,而难以表示它的问题。
    auto在这里的作用也称为返回值占位,它只是为函数返回值占了一个位置,真正的返回值是后面的decltype(_Tx*_Ty)。为何要将返回值后置呢?如果没有后置,则函数声明时为:

    decltype(_Tx*_Ty)multiply(_Tx x, _Ty y)

    而此时_Tx,_Ty还没声明呢,编译无法通过。

  2. 注意事项

    auto 变量必须在定义时初始化,这类似于const关键字。
    定义在一个auto序列的变量必须始终推导成同一类型。例如:

    auto a4 = 10, a5 = 20, a6 = 30;//正确
    auto b4 = 10, b5 = 20.0, b6 = 'a';//错误,没有推导为同一类型

    使用auto关键字做类型自动推导时,依次施加一下规则:
    如果初始化表达式是引用,则去除引用语义。

    int a = 10;
    int &b = a;
    
    auto c = b;//c的类型为int而非int&(去除引用)
    auto &d = b;//此时c的类型才为int&
    
    c = 100;//a =10;
    d = 100;//a =100;

    如果初始化表达式为const或volatile(或者两者兼有),则除去const/volatile语义。

    const int a1 = 10;
    auto  b1= a1; //b1的类型为int而非const int(去除const)
    const auto c1 = a1;//此时c1的类型为const int
    b1 = 100;//合法
    c1 = 100;//非法
    如果auto关键字带上&号,则不去除const语意。
    
    const int a2 = 10;
    auto &b2 = a2;//因为auto带上&,故不去除const,b2类型为const int
    b2 = 10; //非法

    这是因为如何去掉了const,则b2为a2的非const引用,通过b2可以改变a2的值,则显然是不合理的。
    初始化表达式为数组时,auto关键字推导类型为指针。

    int a3[3] = { 1, 2, 3 };
    auto b3 = a3;
    cout << typeid(b3).name() << endl;

    程序将输出

    int *

    若表达式为数组且auto带上&,则推导类型为数组类型。

    int a7[3] = { 1, 2, 3 };
    auto & b7 = a7;
    cout << typeid(b7).name() << endl;

    程序输出

    int [3]

    函数或者模板参数不能被声明为auto

    void func(auto a)  //错误
    {
    //... 
    }

    时刻要注意auto并不是一个真正的类型。
    auto仅仅是一个占位符,它并不是一个真正的类型,不能使用一些以类型为操作数的操作符,如sizeof或者typeid。

    cout << sizeof(auto) << endl;//错误
    cout << typeid(auto).name() << endl;//错误
  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是关于哈夫曼树在C++中的注意事项: 1. 哈夫曼树是一种二叉树,因此需要定义一个二叉树的结构体或***类。 3. 在构造哈夫曼树时,需要将节点按照权值从小到大排序,因此需要定义一个比较函数或者重载运算符来实现排序。 4. 在构造哈夫曼树时,需要使用递归的方法来构造树,因此需要定义一个递归函数来实现。 5. 在编码和解码时,需要使用哈希表来存储字符和对应的编码,因此需要定义一个哈希表的结构体或类来实现。 以下是一个简单的C++代码示例,用于构造哈夫曼树和进行编码和解码: ```c++ #include <iostream> #include <queue> #include <unordered_map> using namespace std; // 定义哈夫曼树节点结构体 struct HuffmanNode { char ch; // 字符 int freq; // 权值 HuffmanNode *left, *right; // 左右子节点 HuffmanNode(char c, int f) : ch(c), freq(f), left(nullptr), right(nullptr) {} }; // 定义最小堆的比较函数 struct Compare { bool operator()(HuffmanNode* a, HuffmanNode* b) { return a->freq > b->freq; } }; // 构造哈夫曼树 HuffmanNode* buildHuffmanTree(string s) { // 统计字符出现的频率 unordered_map<char, int> freq; for (char c : s) { freq[c]++; } // 将字符和对应的频率存储到优先队列中 priority_queue<HuffmanNode*, vector<HuffmanNode*>, Compare> pq; for (auto p : freq) { pq.push(new HuffmanNode(p.first, p.second)); } // 构造哈夫曼树 while (pq.size() > 1) { HuffmanNode* left = pq.top(); pq.pop(); HuffmanNode* right = pq.top(); pq.pop(); HuffmanNode* parent = new HuffmanNode('$', left->freq + right->freq); parent->left = left; parent->right = right; pq.push(parent); } return pq.top(); } // 递归编码 void encode(HuffmanNode* root, string code, unordered_map<char, string>& table) { if (!root) { return; } if (root->ch != '$') { table[root->ch] = code; } encode(root->left, code + "0", table); encode(root->right, code + "1", table); } // 哈夫曼编码 string huffmanEncode(string s) { // 构造哈夫曼树 HuffmanNode* root = buildHuffmanTree(s); // 递归编码 unordered_map<char, string> table; encode(root, "", table); // 将字符串编码为二进制串 string res = ""; for (char c : s) { res += table[c]; } return res; } // 哈夫曼解码 string huffmanDecode(string s, HuffmanNode* root) { string res = ""; HuffmanNode* cur = root; for (char c : s) { if (c == '0') { cur = cur->left; } else { cur = cur->right; } if (cur->ch != '$') { res += cur->ch; cur = root; } } return res; } int main() { string s = "hello world"; string encoded = huffmanEncode(s); cout << "Encoded string: " << encoded << endl; HuffmanNode* root = buildHuffmanTree(s); string decoded = huffmanDecode(encoded, root); cout << "Decoded string: " << decoded << endl; return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值