主頁 > 後端開發 > 《C++ Primer》筆記 第11章 關聯容器

《C++ Primer》筆記 第11章 關聯容器

2021-02-07 06:16:11 後端開發

關聯容器型別 解釋
—— 按關鍵字有序保存元素
map 關聯陣列;保存關鍵字-值對
set 關鍵字即值,即只保存關鍵字的容器
multimap 關鍵字可重復出現的map
multiset 關鍵字可重復出現的set
—— 無序集合
unordered_map 用哈希函陣列織的map
unordered_set 用哈希函陣列織的set
unordered_multimap 哈希組織的map;關鍵字可以重復出現
unordered_multiset 哈希組織的set;關鍵字可以重復出現
  1. 型別mapmultimap定義在頭檔案map中;setmultiset定義在頭檔案set中;無序容器則定義在頭檔案unordered_mapunordered_set中,

    // 統計輸入中每個單詞出現的次數
    map<string, size_t> word_count; // string到size_t的空map
    set<string> exclude = {"The", "But", "And", "Or", "An", "A", "the", "but", "and", "or", "an", "a"};
    string word;
    while(cin >> word)
    	// 只統計不在exclude中的單詞
    	if (exclude.find(word) == exclude.end())
    		++word_count[word]; // 獲取并遞增word的計數器
    
  2. 關聯容器不支持順序容器的位置相關操作,例如push_frontpush_back,原因是關聯容器中元素是根據關鍵字存盤的,這些操作對關聯容器沒有意義,關聯容器也不支持建構式或插入操作這些接受一個元素值和一個數量值的操作,

  3. 關聯容器的迭代器都是雙向的,

  4. 定義關聯容器,當初始化一個map時,必須提供關鍵字型別和值型別,我們將每個關鍵字-值對包圍在花括號中:{key, value}來指出它們一起構成了map中的一個元素,在每個花括號中,關鍵字是第一個元素,值是第二個,

    map<string, size_t> word_count; // 空容器
    // 串列初始化
    set<string> exclude = {"The", "But", "And", "Or", "An", "A", "the", "but", "and", "or", "an", "a"};
    // 三個元素;authors將姓映射為名
    map<string, string> authors = { {"Joyce", "James"}, {"Austen", "Jane"}, {"Dickens", "Charles"} };
    // 定義一個有20個元素的vector
    vector<int> ivec = {0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9};
    // iset包含來自ivec的不重復的10個元素;miset包含所有20個元素
    set<int> iset(ivec.cbegin(), ivec.cend());
    multiset<int> miset(ivec.cbegin(), ivec.cend());
    
  5. 對有序容器——map、multimap、set以及multiset,關鍵字型別必須定義元素比較的方法,默認情況下,標準庫使用關鍵字型別的<運算子來比較兩個關鍵字,在集合型別中,關鍵字型別就是元素型別;在映射型別中,關鍵字型別是元素的第一部分的型別,

  6. 傳遞給排序演算法的可呼叫物件必須滿足與關聯容器中關鍵字一樣的型別要求,

  7. 可以向一個演算法提供我們自定義的比較操作,與之類似,也可以提供自己定義的操作來替代關鍵字上的<運算子,所提供的操作必須在關鍵字型別上定義一個嚴格弱序,可以將嚴格弱序看作“小于等于”,雖然實際定義的操作可能是一個復雜的函式,無論我們怎樣定義比較函式,它必須具備如下基本性質:

    • 兩個關鍵字不能同時“小于等于”對方;如果k1“小于等于”k2,那么k2絕對不能“小于等于”k1,
    • 如果k1“小于等于”k2,且k2“小于等于”k3,那么k1必須“小于等于”k3,
    • 如果存在兩個關鍵字,任何一個都不“小于等于”另一個,那么我們稱這兩個關鍵字是“等價”的,如果k1“等價于”k2,且k2“等價于”k3,那么k1必須“等價于”k3,
  8. 在實際編程中,重要的是,如果一個型別定義了“行為正常”的<運算子,則它可以用作關鍵字型別,

  9. 用來組織一個容器中元素的操作的型別也是該容器型別的一部分,為了指定使用自定義的操作,必須在定義關聯容器型別時提供此操作的型別,

    bool compareIsbn(const Sales_data &lhs, const Sales_data &rhs)
    {
    	return lhs.isbn() < rhs.isbn();
    }
    
    // bookstore中多條記錄可以相同的ISBN
    // 用compareIsbn來初始化bookstore物件,這表示我們向bookstore添加元素時,通過呼叫compareIsbn來為這些元素排序
    // 即,bookstore中的元素以ISBN的順序進行排列
    multiset<Sales_data, decltype(compareIsbn)*> bookstore(compareIsbn);
    
  10. pair的標準庫型別,定義在頭檔案utility中,一個pair保存兩個資料成員,當創建一個pair時,我們必須提供兩個型別名,pair的資料成員將具有對應的型別,兩個型別不要求一樣,

  11. pair的默認建構式對資料成員進行值初始化,也可以為每個成員提供初始化器:

    pair<string, string> anon; // anon是一個包含兩個空string的pair
    pair<string, string> author{"James", "Joyce"};
    
  12. 與其他標準庫型別不同,pair的資料成員是public的,兩個成員分別命名為first和second,我們用普通的成員訪問符號來訪問他們,

  13. map的元素是pair,

pair上的操作 解釋
pair<T1, T2> p; p是一個pair,兩個型別分別為T1和T2的成員都進行了值初始化
pair<T1, T2> p(v1, v2) p是一個成員型別為T1和T2的pair;first和second成員分別用v1和v2進行初始化
pair<T1, T2> p = {v1, v2}; 等價于p(v1, v2)
make_pair(v1, v2) 回傳一個用v1和v2初始化的pair,pair的型別從v1和v2的型別推斷出來
p.first 回傳p的名為first的(公有)資料成員
p.second 回傳p的名為second的(公有)資料成員
p1 relop p2 關系運算子(<、>、<=、>=)按字典序定義:例如,當p1.first < p2.first!(p2.first < p1.first) && p1.second < p2.second成立時,p1 < p2true,關系運算子利用元素的<運算子來實作
p1 == p2或p1 != p2 當first和second成員分別相等時,兩個pair相等,相等性判斷利用元素的==運算子實作
pair<string, int> process(vector<string> &v)
{
	// 處理v
	if (!v.empty())
		return {v.back(), v.back().size()}; // 串列初始化,下述等價
    	// return pair<string, int>(v.back(), v.back().size());
    	// return make_pair(v.back(), v.back().size());
	else
		return pair<string, int>(); // 隱式構造回傳值
}
關聯容器額外的型別別名 解釋
key_type 此容器型別的關鍵字型別
mapped_type 每個關鍵字關聯的型別;只適用于map
value_type 對于set,與key_type相同;對于map,為pair<const key_type, mapped_type>
  1. 對于set型別,key_typevalue_type是一樣的;set中保存的值就是關鍵字,在一個map中,元素是關鍵字-值對,即,每個元素是一個pair物件,包含一個關鍵字和一個關聯的值,由于我們不能改變一個元素的關鍵字,因此這些pair的關鍵字部分是const的,

    set<string>::value_type v1; // v1是一個string
    set<string>::key_type v2; // v2是一個string
    map<string, int>::value_type v3; // v3是一個pair<const string, int>
    map<string, int>::key_type v4; // v4是一個string
    map<string, int>::mapped_type v5; // v5是一個int
    
  2. 當解參考一個關聯容器迭代器時,我們會得到一個型別為容器的value_type的值的參考,對map而言,value_type是一個pair型別,其first成員保存const的關鍵字,second成員保存值,

    // 獲得指向word_count中一個元素的迭代器
    auto map_it = word_count.begin();
    // *map_it是指向一個pair<const string, size_t>物件的參考
    cout << map_it->first; //列印此元素的關鍵字
    cout << " " << map_it->second; // 列印此元素的值
    map_it->first = "new key"; // 錯誤:關鍵字是const的
    ++map_it->second; // 正確:我們可以通過迭代器改變元素
    
  3. 雖然set型別同時定義了iterator和const_iterator型別,但兩種型別都只允許只讀訪問set中的元素,與不能改變一個map元素的關鍵字一樣,一個set中的關鍵字也是const的,可以用一個set迭代器來讀取元素的值,但不能修改:

    set<int> iset = {0,1,2,3,4,5,6,7,8,9};
    set<int>::iterator set_it = iset.begin();
    if (set_it != iset.end())
    {
    	*set_it = 42; // 錯誤:set中的關鍵字是只讀的
    	cout << *set_it << endl; // 正確:可以讀關鍵字
    }
    
  4. 當使用一個迭代器遍歷一個map、multimap、set或multiset時,迭代器按關鍵字升序遍歷元素,

    // 獲得一個指向首元素的迭代器
    auto map_it = word_count.cbegin();
    // 比較當前迭代器和尾后迭代器
    while (map_it != word_count.cend())
    {
    	// 解參考迭代器,列印關鍵字-值對
    	cout << map_it->first << " occurs " << map_it->second << " times" << endl;
    	++map_it; // 遞增迭代器,移動到下一個元素
    }
    
  5. 關聯容器的insert成員向容器中添加一個元素或一個元素范圍,由于map和set包含不重復的關鍵字,因此插入一個已存在的元素對容器沒有任何影響,

  6. insert有兩個版本,分別接受一對迭代器,或是一個初始化器串列,這兩個版本的行為類似對應的建構式(對于一個給定的關鍵字,只有第一個帶此關鍵字的元素才被插入到容器中),

  7. 對一個map進行insert操作時,必須記住元素型別是pair:

    // 向word_count插入word的4種方法
    word_count.insert({word, 1});
    word_count.insert(make_pair(word, 1));
    word_count.insert(pair<string, size_t>(word, 1));
    word_count.insert(map<string, size_t>::value_type(word, 1));
    
關聯容器insert操作 解釋
c.insert(v)或c.emplace(args) v是value_type型別的物件;args用來構造一個元素,對于map和set,只有當元素的關鍵字不在c中時才插入(或構造)元素,函式回傳一個pair,包含一個迭代器,指向具有指定關鍵字的元素,以及一個指示插入是否成功的bool值,對于multimap和multiset,總會插入(或構造)給定元素,并回傳一個指向新元素的迭代器,
c.insert(b, e)或c.insert(il) b和e是迭代器,表示一個c::value_type型別值的范圍;il是這種值的花括號串列,函式回傳void,對于map和set,只插入關鍵字不在c中的元素,對于multimap和multiset,則會插入范圍中的每個元素,
c.insert(p, v)或c.emplace(p, args) 類似insert(v)(或emplace(args)),但將迭代器p作為一個提示,指出從哪里開始搜索新元素應該存盤的位置,回傳一個迭代器,指向具有給定關鍵字的元素,
從關聯容器洗掉元素 解釋
c.erase(k) 從c中洗掉每個關鍵字為k的元素,回傳一個size_type值,指出洗掉的元素的數量
c.erase(p) 從c中洗掉迭代器p指定的元素,p必須指向c中一個真實元素,不能等于c.end(),回傳一個指向p之后元素的迭代器,若p指向c中的尾元素,則回傳c.end()
c.erase(b,e) 洗掉迭代器對b和e所表示的范圍中的元素,回傳e
map和unordered_map的下標操作 解釋
c[k] 回傳關鍵字為k的元素;如果k不在c中,添加一個關鍵字為k的元素,對其進行值初始化
c.at(k) 訪問關鍵字為k的元素,帶引數檢查;若k不在c中,拋出一個out_of_range例外
  1. map和unordered_map容器提供了下標運算子和一個對應的at函式,

  2. set型別不支持下標,因為set中沒有與關鍵字相關聯的“值”,

  3. 我們不能對一個multimap或一個unordered_multimap進行下標操作,因為這些容器中可能有多個值與一個關鍵字相關聯,

  4. 如果關鍵字并不在map中,會為它創建一個元素并插入到map中,關聯值將進行值初始化,

  5. 由于下標運算子可能插入一個新元素,我們只可以對非const的map使用下標操作,

  6. 通常情況下,解參考一個迭代器所回傳的型別與下標運算子回傳的型別是一樣的,但對map則不然:當對一個map進行下標操作時,會獲得一個mapped_type物件;但當解參考一個map迭代器時,會得到一個value_type物件,

  7. 與其他下標運算子相同的是,map的下標運算子回傳一個左值,

  8. 另一方面,有時只是想知道一個元素是否已在map中,但在不存在時并不想添加元素,在這種情況下,就不能使用下標運算子,應該使用find:

    if (word_count.find("foobar") == word_count.end())
    	cout << "foobar is not in the map" << endl;
    
在一個關聯容器中查找元素的操作 解釋
—— lower_bound和upper_bound不適用于無序容器
—— 下標和at操作只適用于非const的map和unordered_map
c.find(k) 回傳一個迭代器,指向第一個關鍵字為k的元素,若k不在容器中,則回傳尾后迭代器
c.count(k) 回傳關鍵字等于k的元素的數量,對于不允許重復關鍵字的容器,回傳值永遠是0或1
c.lower_bound(k) 回傳一個迭代器,指向第一個關鍵字不小于k的元素
c.upper_bound(k) 回傳一個迭代器,指向第一個關鍵字大于k的元素
c.equal_range(k) 回傳一個迭代器pair,表示關鍵字等于k的元素的范圍,若k不存在,pair的兩個成員均等于c.end()
  1. 在multimap或multiset中查找元素

    string search_item("Alain de Botton"); // 要查找的作者
    auto entries = authors.count(search_item); // 元素的數量
    auto iter = authors.find(search_item); // 此作者的第一本書
    // 用一個回圈查找此作者的所有著作
    while (entries)
    {
    	cout << iter->second << endl; // 列印每個題目
    	++iter; // 前進到下一本書
    	--entries; // 記錄已經列印了多少本書
    }
    // 當我們遍歷一個multimap或multiset時,保證可以得到序列中所有具有給定關鍵字的元素
    
  2. 用相同的關鍵字呼叫lower_bound和upper_bound會得到一個迭代器范圍,表示所有具有該關鍵字的元素的范圍,如果關鍵字在容器中,lower_bound回傳的迭代器將指向第一個具有給定關鍵字的元素,而upper_bound回傳的迭代器則指向最后一個匹配給定關鍵字的元素之后的位置,如果元素不在multimap或multiset中,則lower_bound和upper_bound會回傳相等的迭代器——指向一個不影響排序的關鍵字插入位置,

    // authors和search_item的定義,與前面的程式一樣
    // beg和end表示對應此作者的元素的范圍
    for (auto beg = authors.lower_bound(search_item), 
         	end = authors.upper_bound(search_item); 
         	beg != end; 
         	++beg)
    	cout << beg->second << endl; // 列印每個題目
    // lower_bound回傳的迭代器可能指向一個具有給定關鍵字的元素,但也可能不指向,
    // 如果關鍵字不在容器中,則lower_bound會回傳關鍵字的第一個安全插入點——不影響容器中元素順序的插入位置,
    
  3. 直接呼叫equal_range:此函式接受一個關鍵字,回傳一個迭代器pair,若關鍵字存在,則第一個迭代器指向第一個與關鍵字匹配的元素,第二個迭代器指向最后一個匹配元素之后的位置,若未找到匹配元素,則兩個迭代器都指向關鍵字可以插入的位置,

    // authors和search_item的定義,與前面的程式一樣
    // pos保存迭代器對,表示與關鍵字匹配的元素范圍
    for (auto pos = authors.equal_range(search_item); 
         	pos.first != pos.second; 
         	++pos.first)
    	cout << pos.first->second << endl; // 列印每個題目
    // 此程式本質上與前一個使用upper_bound和lower_bound的程式是一樣的,
    
  4. 綜合應用(一個單詞轉換的map):

#include <map>
#include <vector>
#include <iostream>
#include <fstream>
#include <string>
#include <stdexcept>
#include <sstream>

using std::cout;
using std::endl;
using std::getline;
using std::ifstream;
using std::istringstream;
using std::map;
using std::runtime_error;
using std::string;
using std::vector;

map<string, string> buildMap(ifstream &map_file)
{
    map<string, string> trans_map; // holds the transformations
    string key;                    // a word to transform
    string value;                  // phrase to use instead
    // read the first word into key and the rest of the line into value
    while (map_file >> key && getline(map_file, value))
    {
        if (value.size() > 1) // check that there is a transformation
        {
            trans_map[key] = value.substr(1); // skip leading space
        }
        else
        {
            throw runtime_error("no rule for " + key);
        }
    }
    return trans_map;
}

const string &transform(const string &s, const map<string, string> &m)
{
    // the actual map work; this part is the heart of the program
    auto map_it = m.find(s);
    // if this word is in the transformation map
    if (map_it != m.cend())
    {
        return map_it->second; // use the replacement word
    }
    else
    {
        return s; // otherwise return the original unchanged
    }
}

// first argument is the transformations file;
// second is file to transform
void word_transform(ifstream &map_file, ifstream &input)
{
    auto trans_map = buildMap(map_file); // store the transformations

    // for debugging purposes print the map after its built
    cout << "Here is our transformation map: \n\n";
    for (auto entry : trans_map)
    {
        cout << "key: " << entry.first << "\tvalue: " << entry.second << endl;
    }
    cout << "\n\n";

    // do the transformation of the given text
    string text;                 // hold each line from the input
    while (getline(input, text)) // read a line of input
    {
        istringstream stream(text); // read each word
        string word;
        bool firstword = true; // controls whether a space is printed
        while (stream >> word)
        {
            if (firstword)
            {
                firstword = false;
            }
            else
            {
                cout << " "; // print a space between words
            }
            // transform returns its first argument or its transformation
            cout << transform(word, trans_map); // print the output
        }
        cout << endl; // done with this line of input
    }
}

int main(int argc, char **argv)
{
    // open and check both files
    if (argc != 3)
    {
        throw runtime_error("wrong number of arguments");
    }

    ifstream map_file(argv[1]); // open transformation file
    if (!map_file)              // check that open succeeded
    {
        throw runtime_error("no transformation file");
    }

    ifstream input(argv[2]); // open file of text to transform
    if (!input)              // check that open succeeded
    {
        throw runtime_error("no input file");
    }

    word_transform(map_file, input);

    return 0; // exiting main will automatically close the files
}
  1. 管理桶:無序容器在存盤上組織為一組桶,每個桶保存零個或多個元素,無序容器使用一個哈希函式將元素映射到桶,為了訪問一個元素,容器首先計算元素的哈希值,它指出應該搜索哪個桶,容器將具有一個特定哈希值的所有元素都保存在相同的桶中,如果容器允許重復關鍵字,所有具有相同關鍵字的元素也都會在同一個桶中,因此,無序容器的性能依賴于哈希函式的質量和桶的數量和大小,
無序容器管理操作 解釋
桶介面 ——
c.bucket_count() 正在使用的桶的數目
c.max_bucket_count() 容器能容納的最多的桶的數量
c.bucket_size(n) 第n個桶中有多少個元素
c.bucket(k) 關鍵字為k的元素在哪個桶中
桶迭代 ——
local_iterator 可以用來訪問桶中元素的迭代器型別
const_local_iterator 桶迭代器的const版本
c.begin(n), c.end(n) 桶n的首元素迭代器和尾后迭代器
c.cbegin(n), c.cend(n) 與前兩個函式類似,但回傳const_local_iterator
哈希策略 ——
c.load_factor() 每個桶的平均元素數量,回傳float值
c.max_load_factor() c試圖維護的平均桶大小,回傳float值,c會在需要時添加新的桶,以使得load_factor<=max_load_factor
c.rehash(n) 重組存盤,使得bucket_count>=n且bucket_count>size/max_load_factor
c.reserve(n) 重組存盤,使得c可以保存n個元素且不必rehash
  1. 默認情況下,無序容器使用關鍵字型別的==運算子來比較元素,它們還使用一個hash<key_type>型別的物件來生成每個元素的哈希值,標準庫為內置型別(包括指標)提供了hash模板,還為一些標準庫型別,包括string和智能指標型別定義了hash,因此,我們可以直接定義關鍵字是內置型別(包括指標型別)、string還是智能指標型別的無序容器,

  2. 但是,我們不能直接定義關鍵字型別為自定義型別別的無序容器,我們需要提供函式來替代==運算子和哈希值計算函式,

    size_t hasher(const Sales_data &sd)
    {
        // 我們的hasher函式使用一個標準庫hash型別物件來計算ISBN成員的哈希值
        // 該hash型別建立在string型別之上
    	return hash<string>()(sd.isbn());
    }
    bool eqOp(const Sales_data &lhs, const Sales_data &rhs)
    {
        // eqOp函式通過比較ISBN號來比較兩個Sales_data
    	return lhs.isbn() == rhs.isbn();
    }
    
    using SD_multiset = unordered_multiset<Sales_data, decltype(hasher)*, decltype(eqOp)*>;
    // 引數是桶大小、哈希函式指標和相等性判斷運算子指標
    SD_multiset bookstore(42, hasher, eqOp);
    
  3. 如果我們的類定義了==運算子,則可以只多載哈希函式,

    // 使用FooHash生成哈希值;Foo必須有==運算子
    unordered_set<Foo, decltype(FooHash)*> fooSet(10, FooHash);
    
  4. 有序容器使用比較函式來比較關鍵字,從而將元素按順序存盤,默認情況下,比較操作是采用關鍵字型別的<運算子,無序容器使用關鍵字型別的==運算子和一個hash<key_type>型別的物件來組織元素,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/257306.html

標籤:C++

上一篇:C++面向物件:C++ 介面(抽象類)

下一篇:Qt update重繪之原始碼分析(一)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more