程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++ map.insert 傳參類型不同,構造/析構次數不同,map.insert

C++ map.insert 傳參類型不同,構造/析構次數不同,map.insert

編輯:C++入門知識

C++ map.insert 傳參類型不同,構造/析構次數不同,map.insert


1. 傳參方式

使用 insert 為 map 插值時,insert 的傳參包含以下幾種可能:

  • make_pair 生成對象
  • pair(key_type, value_type) 生成對象
  • pair(const key_type, value_type) 生成對象
  • map<key_type, value_type>::value_type 生成對象

不同的傳參,導致不同次數的構造 / 析構函數調用。

2. 測試代碼與結果

/* 在 map 中不同的 insert 傳參類型,導致的不同次數的構造/析構函數調用。 */ #include <iostream> #include <vector> #include <map> #include <string> using namespace std; class Data { public: Data(void) { cout << "Constructor" << endl; } Data(const Data& other) { cout << "Copy Constructor" << endl; } Data& operator=(const Data& other) { cout << "Assignment operator" << endl; return *this; } ~Data(void) { cout << "Destructor" << endl; } }; class Tracker { public: Tracker(string name) { _name = name; cout << "### Testing " << name << endl; } ~Tracker(void) { cout << "### Done" << endl << endl; } private: string _name; }; int main () { { Tracker tracker("insert data using make_pair"); map<int, Data> c; Data d = Data(); cout << "---- Begin ---- " << endl; c.insert(make_pair(1, d)); cout << "----- End -----" << endl; } { Tracker tracker("insert data using pair<key_type, value_type>"); map<int, Data> c; Data d = Data(); cout << "---- Begin ---- " << endl; c.insert(pair<int, Data>(1, d)); cout << "----- End -----" << endl; } { Tracker tracker("insert data using pair<const key_type, value_type>"); map<int, Data> c; Data d = Data(); cout << "---- Begin ---- " << endl; c.insert(pair<const int, Data>(1, d)); cout << "----- End -----" << endl; } { Tracker tracker("insert data using map<key_type, value_type>::value_type"); map<int, Data> c; Data d = Data(); cout << "---- Begin ---- " << endl; c.insert(map<int, Data>::value_type(1, d)); cout << "----- End -----" << endl; } return 0; } View Code

3. 調用流程分析

3.1 value_type 2 次 Copy Constructor 產生 1 個臨時變量

分解後的 value_type 調用細節對比圖

3.2 pair(const key_type, value_type) 與 value_type 過程相同

原因:value_type 的定義是: pair<const key_type,mapped_type> 

參見:http://www.cplusplus.com/reference/map/map/

3.3 pair(key_type, value_type)  3 次 Copy Constructor 產生 2 個臨時變量

根據下圖的流程拆解可以看出,非 const 的 key_type 導致 insert 過程增加了一次 Copy Constructor

3.4 make_pair 4 次 Copy Constructor 產生 3 個臨時變量

新增的一次 Copy Constructor 來自於 make_pair 過程。

make_pair 的過程是:Constructs a pair object with its first element set to x and its second element set to y.

偽代碼如下:

template <class T1,class T2>
  pair<T1,T2> make_pair (T1 x, T2 y)
  {
    return ( pair<T1,T2>(x,y) );
  }

參見:http://www.cplusplus.com/reference/utility/make_pair/?kw=make_pair

make_pair 時的 key 使用 const 變量,並未能減少 insert 階段的一次 Copy Constructor

const int k = 1;
c.insert(make_pair(k, d));

4. 結果分析


類的設計,構造函數與析構函數 c/c++

類是編程人員表達自定義數據類型的C++機制。它和C語言中的結構類似,C++類

支持數據抽象和面向對象的程序設計,從某種意義上說,也就是數據類型的設

計和實現。

一、類的設計
1.類的聲明

class 類名
{
private: //私有
...
public: //公有
...
};

2.類的成員
一般在C++類中,所有定義的變量和函數都是類的成員。如果是變量,我們就叫

它數據成員如果是函數,我們就叫它成員函數。
3.類成員的可見性
private和public訪問控制符決定了成員的可見性。由一個訪問控制符設定的可

訪問狀態將一直持續到下一個訪問控制符出現,或者類聲明的結束。私有成員

僅能被同一個類中的成員函數訪問,公有成員既可以被同一類中的成員函數訪

問,也可以被其他已經實例化的類中函數訪問。當然,這也有例外的情況,這

是以後要討論的友元函數。
類中默認的數據類型是private,結構中的默認類型是public。一般情況下,變

量都作為私有成員出現,函數都作為公有成員出現。
類中還有一種訪問控制符protected,叫保護成員,以後再說明。
4.初始化
在聲明一個類的對象時,可以用圓括號()包含一個初始化表。

看下面一個例子:

#include iostream.h

class Box
{
private:
int height,width,depth; //3個私有數據成員
public:
Box(int,int,int);
~Box();
int volume(); //成員函數
};

Box::Box(int ht,int wd,int dp)
{
height=ht;
width=wd;
depth=dp;
}

Box::~Box()
{
//nothing
}

int Box::volume()
{
return height*width*depth;
}

int main()
{
Box thisbox(3,4,5); //聲明一個類對象並初始化
cout< return 0;
}

當一個類中沒有private成員和protected成員時,也沒有虛函數,並且不是從

其他類中派生出來的,可以用{}來初始化。(以後再講解)
5.內聯函數
內聯函數和普通函數的區別是:內聯函數是在編譯過程中展開的。通常內聯函

數必須簡短。定義類的內聯函數有兩種方法:一種和C語言一樣,在定義函數時

使用關鍵字inline。如:

inline int Box::volume()
{
return height*width*depth;
}

還有一種方法就是直接在類聲明的內部定義函數體,而不是僅僅給出一個函數

原型。我們把上面的函數簡化一下:

#include iostream.h

class Box
{
private:
int height,width,depth;
public:
Box(int ht,int wd,int dp)
{
height=ht;
width=wd;
depth=dp;
}
~Box();
int volume()
{
return height*width*depth;
}
};

int main()
{
Box thisbox(3,4,5); //聲明一個類對象並初始化
cout< return 0;
}

這樣,兩個函數都默認為內聯函數了。...余下全文>>
 

c++ 中使用std::map< key, Type > 時發現map容器的異常,會對Type在沒有構造的情況下,進行多次析構

構造函數 還有復制構造函數。 A(A&){}//調用了2次復制構造
mapa[1] = A(); //這裡能編譯。pair<key,value> 才行吧。
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved