首页 文章

C复制构造函数,指向指针向量的指针

提问于
浏览
0

我有一个类 A ,它有一个指向指针向量( current )的成员,该向量包含一对整数和类 B 的对象 . 我需要能够为类 A 的对象创建副本,为此我使用 Clone 函数(参见下面的代码) . 但是,当我使用此函数时,指针似乎指向相同的内存位置,而不是指向不同的内存位置 . 我认为解决这个问题的方法是为我的类实现一个复制构造函数,以便能够正确地复制我的对象,但我没有这样做 .

以下是我的类的外观以及我实现复制构造函数的几次尝试:

class A {
public:
    A();
    A(const A &a);
    ~A();
    A* Clone() {return new A(*this);}
    std::vector<std::pair<unsigned int, B*>> *current;
};

编辑:构造函数和析构函数实现如下:

A::A() {
    current = new vector<std::pair<unsigned int, B*>>;
}

A::~A() {
    std::vector<std::pair<unsigned int, B*>>::iterator cit = current->begin(), cend = current->end();
    for (; cit != cend; ++cit) {
        delete cit->second;
    }
    delete current;
}

选项1:

A::A(const A &a){
    *current = *a.current;
}

选项#2:

A::A(const A &a){
    for(int i = 0; i < current->size(); i++) {
        (*current)[i] = (*a.current)[i];
    }
}

选项#3:

A::A(const A &a){
    for(int i = 0; i < current->size(); i++) {
        (*current)[i].first = (*a.current)[i].first;
        (*current)[i].second = new B((*a.current)[i].second);
    }
}

选项#1和#2给我分段错误,而#3我得到错误: no match for operator *

哪个是实现复制构造函数的正确方法,我的 Clone 函数应该以不同的方式实现吗?

1 回答

  • 0

    您的构造函数根本不初始化 current 成员 . 在任何选项中 .

    从那里,访问它的值(即名为 current 的指针的值)给出了未定义的行为 . 解除引用它也是如此 . 因此,所有选项(及其变体)中的 *current*a.current 的用法都会给出未定义的行为 .

    如果您坚持成员 current 必须是指针,则必须在所有构造函数中初始化它 . 例如,构造函数 A::A() (您尚未显示)必须类似于

    A::A() : current(new std::vector<std::pair<unsigned int, B*>>(0))
     {
         //   initialised current with no elements
         // add pairs to the vector
    
         current->push_back(std::make_pair(0U, new B));
         current->push_back(std::make_pair(42U, new B));
     }
    

    并且复制构造函数必须以类似于的东西开头

    A::A(const A &a) : current (new std::vector<std::pair<unsigned int, B *>>(a.current->size())
    {
        for(int i = 0; i < current->size(); i++)
        {
            (*current)[i].first = (*(a.current))[i].first;
            (*current)[i].second = new B((*(a.current))[i].second);
        }
    }
    

    但更一般地说, current 实际上没有理由成为使用operator new 创建的指针 . 在这种情况下,构造函数可以简化为

    A::A() : current(0)
     {
         // add pairs to the vector
    
         current.push_back(std::make_pair(0U, new B));
         current.push_back(std::make_pair(42U, new B));
     }
    

    和复制构造函数

    A::A(const A &a) : current (a.current.size())
    {
        for(int i = 0; i < current.size(); i++)
        {
            current[i].first = a.current[i].first;
            current[i].second = new B(a.current[i].second);
        }
    }
    

    您还没有提供令人信服的信息来表明 current 需要 vector<pair<unsigned, B *>> 而不是 vector<pair<unsigned, B>> . 如果向量不需要保存指针(即它直接保存对象),那么实际上,您根本不需要定义复制构造函数 - 编译器生成的默认值就足够了 . 并且您的代码根本不需要使用operator new (可能在 A::Clone() 中除外) .

    请注意,如果您确实需要手动滚动复制构造函数,则可能还需要手动滚动 operator=() 和析构函数 . 查找"rule of three"(在C 11之前)或(C 11及更高版本)"rule of five"和"rule of zero"以获取更多信息 .

相关问题