指向对象的指针出现混淆

Confusion in Pointer to the object

本文关键字:指针 对象      更新时间:2023-10-16

在下面的代码中,我定义了int类型的map和类a的对象。我定义了两个函数,funwithPointer和funwithoutPointer。如您所见,我试图在类的对象中增加投票,并将其添加到map中。如果我使用对象的指针,那么在调用第三次时,我得到2的投票,而在声明没有指针的对象(funwithoutPointer)时,我不能增加投票超过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);
}

In function

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 &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();

有很多共性。要么使用对对象的引用来更改它,要么使用指向该对象的指针

问题在这一行:

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

您正在创建映射中对象的副本,命名为a,然后试图修改该副本。简单的解决方案是使用reference:

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 Jester-Young):

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();

你想要的是:

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();
        }
    }
}

如果没有找到,将向映射中插入一个新对象;如果找到了,则允许修改映射中的实际对象