编辑看起来我没有以一种好的方式解释自己。我的问题不是关于3的规则,或者是如何以一种好的方式实现它。我的问题是为什么当使用逗号时,在完成序列后调用析构函数而不是在变量离开作用域时调用,我的意思是,当逗号之间的所有函数都已完成时,objets只会被销毁,你可以看到它在析构函数中添加了一个cout。
在此示例中,
#include <iostream>
#include <cstring>
using namespace std;
class Libro {
char* titulo_; int paginas_;
public:
Libro() : titulo_(new char[1]), paginas_(0) {*titulo_= 0;}
Libro(const char* t, int p) : paginas_(p) {
titulo_ = new char[strlen(t) + 1];
strcpy(titulo_, t);
}
~Libro() { delete[] titulo_; }
void paginas(int p) { paginas_ = p; }
int paginas() const { return paginas_; }
char* titulo() const { return titulo_; }
};
void mostrar(Libro l) {
cout << l.titulo() << " tiene " << l.paginas() << " paginas" << endl;
}
int main() {
Libro l1("Fundamentos de C++", 474), l2("Por Fin: C ISO", 224), l3;
l3 = l1;
mostrar(l1), mostrar(l2), mostrar(l3);
}
尽管没有定义复制构造函数,并且编译器提供的默认复制构造函数在这种情况下无效,但执行是正确的并且它在对 mostrar(l1),mostrar的调用中显示正确的信息( l2),mostrar(l3); 。
但是,如果我们使用 mostrar(l1); mostrar(L2); mostrar(l3); 相反,我们会有预期的错误,最后一次调用无法正确显示最后一次调用,因为副本没有正确完成。 你知道使用之间有什么不同吗?为什么这段代码在您使用时有效?
答案 0 :(得分:2)
您尚未编写复制构造函数或复制赋值运算符。 The Rule of 3告诉我们,无论何时编写析构函数,复制赋值运算符和复制构造函数也应如此。你还没有写过,所以让我们来看看会发生什么:
l3 = l1
在此行中调用implicitly defined copy assignment operator,其定义如下:
Libro& Libro::operator=(const Libro& rhs) {
this.tiulo_ = rhs.titulo_;
this.paginas_ = rhs.paginas_;
}
this.tiulo_ = rhs.titulo_
这意味着l1
和l3
对象都指向由l1
的构造函数动态分配的“Fundamentos de C ++”字符串l3.~Libro()
被隐式调用为l3
leaves scope,它会调用delete [] titulo_
销毁动态分配l3
成员的“Fundamentos de C ++”也是l1
的{{1}}成员。titulo_
也会被隐式调用,会调用l1.~Libro()
但是这次会员被delete [] titulo_
删除,留下范围for a deleted pointer:将其传递给释放函数(双删除)是未定义的行为
因此,您的问题不是l3
与,
,而是因为不遵循3规则而导致的双重删除。
如果我可以,而不是建议你创建一个复制构造函数和复制赋值运算符,我建议你不要使用;
并使用string
在`对,你的代码将是这很简单:
Libro
这当然要求您明确输出每个成员,例如:
pair<string, int> l1 = make_pair("Fundamentos de C++"s, 474), l2 = make_pair("Por Fin: C ISO"s, 224), l3;