【问题标题】:Value -like implementation of copy constructor and assignment operator复制构造函数和赋值运算符的类似值的实现
【发布时间】:2019-12-10 15:56:29
【问题描述】:

几个月前我问了一个关于复制构造函数和赋值运算符的问题,但我并没有真正解决它,现在我又遇到了同样的问题。 我必须实现包含指针的类的复制构造函数、赋值运算符和析构函数,并且实现必须是类值的,即不同的对象不能指向同一个变量。 假设我有这个代码:

class A{};
class B{
A* item;
int c;
public: 
B(const A& a, int c_): item(new A(a)), c(c_){};
B(const B& b) //copy constructor
B& operator=(const B & b); //assignment operator
~B(); //destructor
}

现在,在我的很多示例中,对这些元素进行编码的正确方法是:

// copy constructor
B::B(const B& b){
    item = new A(*(b.item));
    c=b.c;
}

这是第一个问题,问题是为什么我需要创建一个新的 A 对象,而不是仅仅将 b.item 指向的值分配给 (*this).item。上次有人告诉我分配或延迟未初始化的指针可能会导致奇怪的行为。

// assignment operator

B::operator=(const B& b){
    if(this != &b){
        c=b.c;
        delete item;
        item = new A (*(b.item));
}
}

我可能理解复制构造函数需要 new 运算符,但我为什么要删除项目 并重新分配另一个 A 对象,而不是仅仅复制 b.item 指向的值 this->item?每当代码使用赋值操作符时,A里面的指针都会被初始化,所以就不存在赋值给未初始化指针的问题了,为什么要按照这个过程呢?

【问题讨论】:

  • "问题是我需要创建一个新的 A 对象的原因" 但是...这就是您想要的。您在这里说过:“实现必须是类似值的,即不同的对象不能指向同一个变量”。这怎么可能发生?
  • 如果您的问题是关于分配运算符,那么您应该删除讨论复制构造函数的文本。
  • 在赋值运算符中我可以这样做:*item = *(b.item);而不是:删除项目; item = new A(*(b.item));
  • 好吧,我想确认一下复制构造函数,如果我理解的是正确的,以及关于赋值运算符的答案。
  • @Peanojr: "我可以这样做吗:*item = *(b.item); 而不是:item = new A(*(b.item)); 在复制构造函数中?” 你似乎没有意识到你在问你是否可以获取一个不指向任何东西的指针并取消引用它。因为这就是代码要做的事情。基本上和写A *item; *item = <whatever>没什么区别。

标签: c++


【解决方案1】:

如果您有一个对象b1,并且您像这样创建一个副本b2

B b1;
B b2(b1);

那么您必须创建一个新的A 对象供b2.item 引用,否则它们将引用同一个项目:因此您需要B 的复制构造函数中的new A

现在考虑在赋值下会发生什么:

B b1;
B b2;
b2=b1;

在这种情况下,默认的复制赋值运算符也会做错事:它将item指针从b1复制到b2,所以现在b1b2将指向同一个A。因此,您需要编写一个复制赋值运算符。

由于每个 B 都拥有自己的 A,因此您有两种选择:根据您的示例复制赋值运算符销毁并重新创建 A 对象,或者直接分配包装的对象:

B& B::operator=(B const& other){  // delete and recreate
  if(&other!=this){
    c=other.c;
    delete item;
    item=new A(*other.item);
  }
  return *this;
}

B& B::operator=(B const& other){  // assign the item
  if(&other!=this){
    c=other.c;
    *item=*other.item;
  }
  return *this;
}

哪个最好取决于A 的类型及其一般行为。例如如果A不能被分配,那么你必须删除并重新创建,而如果它可以被分配,那么你可能希望这样做。

【讨论】:

    猜你喜欢
    • 2011-06-09
    • 1970-01-01
    • 2012-06-27
    • 2011-07-19
    • 1970-01-01
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多