You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++对象实例销毁后仍留存于列表中的问题求助

分析你的Member类问题与修复方案

首先我先把你没写完的类定义补全,整理出完整的框架(推测你原本要写follow和unfollow成员函数):

// Member.h
#include <list>
using namespace std;

class Member {
private:
    bool isCopy;
    static int counter;
    int id;
    list<Member*> following;
    list<Member*> followers;

public:
    Member();
    Member(const Member &p2);
    ~Member();
    void follow(Member& other);
    void unfollow(Member& other);
    // 补充常用的统计方法
    int getFollowingCount() const;
    int getFollowersCount() const;
};

接下来我针对社交网络成员类常见的坑,逐一分析并给出修复方案:

1. 静态计数器的初始化问题

静态成员变量必须在类外部初始化,否则编译时会出现链接错误。你需要在Member.cpp中添加:

int Member::counter = 0;

2. 拷贝构造函数的风险

你定义了isCopy成员,应该是想区分原生对象和拷贝对象,但拷贝这类包含指针列表的对象很容易出问题——比如拷贝后的对象会和原对象共享同一批关注/粉丝指针,析构时会触发double free。

在社交网络场景下,成员对象应该是唯一的,更合理的做法是直接禁用拷贝:

// 在类的public区域添加
Member(const Member&) = delete;
Member& operator=(const Member&) = delete;

如果确实需要拷贝,必须实现深拷贝,但这在实际业务逻辑里意义不大,毕竟没人会需要一个和原账号完全一样的副本。

3. follow函数的双向逻辑错误

关注操作必须是双向的:当前成员要把对方加入自己的following列表,同时对方要把当前成员加入followers列表,不然粉丝数和关注数会完全对不上。

正确的实现:

#include <algorithm> // 需要用到find函数

void Member::follow(Member& other) {
    // 禁止关注自己
    if (this == &other) return;
    // 检查是否已经关注过,避免重复添加
    auto it = find(following.begin(), following.end(), &other);
    if (it == following.end()) {
        following.push_back(&other);
        other.followers.push_back(this);
    }
}

4. unfollow函数的双向移除逻辑

取消关注同样要做双向操作:从自己的following中移除对方,同时从对方的followers中移除自己。

正确的实现:

void Member::unfollow(Member& other) {
    if (this == &other) return;
    // 利用list的remove方法直接移除指定指针
    following.remove(&other);
    other.followers.remove(this);
}

5. 析构函数的注意事项

你的following和followers列表里存的是指向其他Member对象的指针,但这些对象不是当前对象创建的(通常是独立在堆上new出来的),所以析构函数里绝对不能delete这些指针,否则会导致其他对象被提前销毁,引发未定义行为。

如果需要在成员销毁时清理关联关系,可以这么写:

Member::~Member() {
    // 通知所有被我关注的人,移除我在他们粉丝列表里的记录
    for (auto followed : following) {
        followed->followers.remove(this);
    }
    // 通知所有我的粉丝,移除我在他们关注列表里的记录
    for (auto follower : followers) {
        follower->following.remove(this);
    }
    // 清空自己的列表
    following.clear();
    followers.clear();
    counter--; // 如果counter是统计当前活跃成员数的话
}

6. 构造函数的实现

构造函数需要初始化id和计数器:

Member::Member() : isCopy(false), id(++counter) {
    // 列表会默认初始化为空,不需要额外操作
}

补充:统计方法的实现

为了方便获取关注数和粉丝数,补充两个成员函数:

int Member::getFollowingCount() const {
    return following.size();
}

int Member::getFollowersCount() const {
    return followers.size();
}

最后可以用这段代码测试基本逻辑:

#include <iostream>
using namespace std;

int main() {
    Member a;
    Member b;
    Member c;

    a.follow(b);
    a.follow(c);
    b.follow(a);

    cout << "a的关注数:" << a.getFollowingCount() << endl; // 输出2
    cout << "a的粉丝数:" << a.getFollowersCount() << endl; // 输出1
    cout << "b的关注数:" << b.getFollowingCount() << endl; // 输出1
    cout << "b的粉丝数:" << b.getFollowersCount() << endl; // 输出1

    a.unfollow(b);
    cout << "a的关注数:" << a.getFollowingCount() << endl; // 输出1
    cout << "b的粉丝数:" << b.getFollowersCount() << endl; // 输出0

    return 0;
}

内容的提问来源于stack exchange,提问作者Tal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:36:56