2014-07-16 225 views
0

在下面的代碼中,我定義了int的映射和類A的對象。我定義了兩個函數funwithPointer和funwithoutPointer。正如你所看到的,我試圖在類的對象中增加投票並將其添加到地圖中。如果我使用對象的指針,那麼在第三次調用時,我會在沒有指針(funwithoutPointer)的情況下聲明對象時得到2票,無論我多少次調用該函數,我都不能將投票增加到1以上。有什麼問題 ?指向對象的指針混亂

#include<iostream> 
#include<map> 
using namespace std; 
class A{ 
    public: 
     int x;int vote; 
     A(int a):x(a),vote(0){} 
     void change(){ 
      cout<<vote<<endl; 
      vote++;} 
}; 
void funwithPointer(map<int,A>& m){ 
for(int i=0;i<5;i++){ 
     if(m.find(i)==m.end()){ 
      A* a=new A(10); 
      a->change(); 
      m.insert(pair<int,A>(i,*a)); 
     } 
     else{ 
      A* a=&m.find(i)->second; 
      a->change(); 
     } 
    } 
} 
void funwithoutPointer(map<int,A>& m){ 
for(int i=0;i<5;i++){ 
     if(m.find(i)==m.end()){ 
      A a= A(10); 
      a.change(); 
      m.insert(pair<int,A>(i,a)); 
     } 
     else{ 
      A a=m.find(i)->second; 
      a.change(); 
     } 
    } 
} 
int main(){ 
    map<int,A> m; 
    funwithoutPointer(m); 
    funwithoutPointer(m); 
    funwithoutPointer(m); 
} 

回答

1

在功能

void funwithoutPointer(map<int,A>& m){ 
for(int i=0;i<5;i++){ 
     if(m.find(i)==m.end()){ 
      A a= A(10); 
      a.change(); 
      m.insert(pair<int,A>(i,a)); 
     } 
     else{ 
      A a=m.find(i)->second; 
      a.change(); 
     } 
    } 
} 

陳述

  A a=m.find(i)->second; 
      a.change(); 

您創建一個類型的新對象,並增加其數據成員。它與地圖中的相應對象沒有任何共同之處。以下列方式更改這些語句

  A &a = m.find(i)->second; 
      a.change(); 

即使用對地圖中對象的引用。或代替這兩個語句,你可以寫下面的方式

  m.find(i)->second.change(); 

正如你可以在第一功能這兩個說法

  A &a = m.find(i)->second; 
      a.change(); 

和語句之間看到

  A* a=&m.find(i)->second; 
      a->change(); 

有很多共同。要麼你使用一個對象的引用,它還是一個指針改變這個對象

1

問題是在這一行:

A a=m.find(i)->second; 

您正在對象的副本地圖,名爲a然後試圖修改該副本。簡單的解決辦法可能是使用參考:

A &a=m.find(i)->second; 

請注意,您的代碼是相當無效的,更快(更簡單的解決方案)可能是:

auto f = map.find(i); 
if(f == map.end()) 
    f = m.insert(std::make_pair(i, A(10))).first; 
f->second.change(); 

這消除了std::map::find()完全不必要的額外調用,這是相當昂貴。

另一個更有效的解決方案(感謝Chris小丑 - 楊):

auto f = map.lower_bound(i); 
if(f == map.end() || f->first != i) 
    f = m.insert(f, std::make_pair(i, A(10))); 
f->second.change(); 
+0

更快的是使用'lower_bound'而不是'find',那麼如果結果與'end()'相同或者鍵是不同於'我',那麼d o暗示插入。 :-) –

+0

因此:'auto f(map.find(i)); if(f == map.end()|| f-> first!= i)m.insert(f,std :: make_pair(...));否則......' –

+0

@Slava如果我使用m,插入(對(i,a));再次調用change()函數後。那就是我插入a的更新版本。 – user3747190

0

你想要的是這樣的:

void funwithoutPointer(map<int,A>& m){ 
    for(int i=0;i<5;i++){ 
     map<int,A>::iterator iFind = m.find(i); 
     if(iFind==m.end()){ 
      A a(10); 
      a.change(); 
      m[i] = a; 
     } 
     else{ 
      iFind->second.change(); 
     } 
    } 
} 

這將插入一個新的對象到地圖中如果沒有找到或允許您修改地圖中的實際對象(如果發現的話)