我的程序可以正常运行,并且可以复制对象,但是当我使用复制分配(=)时,它仍然可以正常运行。为什么不给出错误?

时间:2019-08-02 17:22:50

标签: c++ codeblocks

我没有重载(=)运算符,但它在代码块中仍然可以正常运行。但是,当我在C ++ shell上运行此代码时,它成功编译,但是输出为空。有人可以解释一下,即使我没有为拷贝分配编写代码,为什么它仍可以在代码块中正常运行?

还有另一个问题...

如果在第1行上将返回类型更改为string而不是string&,它将显示错误(关于临时变量),但是如果我将第2行的代码更改为dummy(dummy& abc : ptr(new string (abc.print())),则程序运行正常(尽管第1行的返回类型为string)。为什么会这样?

class dummy {
  string* ptr;

 public:
  dummy(string ab) {
    ptr = new string;
    ptr = &ab;
  }
  ~dummy() { delete ptr; }
  string& print() { return *ptr; }  // line1
  dummy(dummy& abc) {
    ptr = new string;
    ptr = &(abc.print());
  }  // line2
  dummy(){};
};

int main() {
  dummy x("manzar");
  dummy y;
  y = x;

  cout << x.print();
  cout << "\n" << y.print();
}

我没想到它可以正常运行,但是它运行良好。它将内容从x复制到y

2 个答案:

答案 0 :(得分:2)

代码会在编译器自动为您生成赋值运算符时进行编译。有关何时发生和不发生的完整规则,请参见https://en.cppreference.com/w/cpp/language/copy_assignment。另请参见What is The Rule of Three?

您的代码无法在cpp shell上运行的原因可能是由于各种未定义的行为,包括(但可能不限于):

  1. 违反三个规则:What is The Rule of Three?
  2. 您的dummy(string ab)构造函数存储一个指向临时变量的指针。 ptr = &ab;应该是*ptr = ab;
  3. 您的dummy(dummy& abc)副本构造函数应为dummy(const dummy& abc),再次ptr = &(abc.print());应该为*ptr = abc.print();
  4. 您的默认构造函数dummy()应该将ptr初始化为nullptr
  5. print()应该检查ptr是否不为空。

答案 1 :(得分:2)

这是C ++规范的一部分,默认情况下,如果类定义中未包含用户定义的副本分配运算符,则编译器将生成默认的副本分配运算符。这样会自动生成其他几个运算符和函数。其他的是默认构造函数,副本构造函数,move构造函数,move赋值运算符和析构函数。

副本分配的默认行为是复制对象的每个非静态成员-如果对象是POD类型,还是真正执行一个对象,则此副本是“简单地”完成的逐成员复制,但结果相同。对于无法生成默认复制行为的情况,还存在一些复杂性:如果类具有const的非静态成员,则该类为非静态成员。如果它具有一个非静态成员,而该成员本身没有副本分配运算符,等等。

从C ++ 11开始,您可以选择不让编译器通过将它们分配给关键字 delete 来生成任何这些特殊成员函数。

例如,在代码中添加

dummy& operator=(const dummy &) = delete;

按照虚拟的定义,程序将不再编译。