和 ;? 之间的区别?

Difference between , and ;?

本文关键字:区别 之间      更新时间:2023-10-16

>EDIT看起来我没有很好地解释自己。我的问题不是关于3法则,也不是关于如何以良好的方式实施它。我的问题是为什么在使用逗号时,析构函数是在完成序列后调用的,而不是在变量离开范围时调用的,我的意思是,只有在逗号之间的所有函数都完成后才会销毁对象,您可以看到它向析构函数添加了一个 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(;相反,我们将遇到预期的错误,最后一次调用将无法正确显示最后一次调用,因为复制没有正确完成。 你知道使用 和 ; 之间的区别是什么吗?为什么当你使用时这段代码有效?

您尚未编写复制构造函数或复制赋值运算符。3 法则告诉我们,无论何时编写析构函数,复制赋值运算符和复制构造函数也应该如此。你也没有写,所以让我们看看会发生什么:

  1. l3 = l1在此行中调用隐式定义的复制赋值运算符,该运算符将定义如下:

Libro& Libro::operator=(const Libro& rhs) {
this.tiulo_ = rhs.titulo_;
this.paginas_ = rhs.paginas_;
}
  1. >this.tiulo_ = rhs.titulo_这意味着l1l3对象都指向由l1的构造函数动态分配的"Fundamentos de C++"字符串
  2. l3.~Libro()被隐含地调用,因为l3离开了范围,这将调用delete [] titulo_破坏l3的"Fundamentos de C++"动态分配的成员,这也是l1titulo_成员
  3. l1.~Libro()也是隐式调用的,但是这次该成员被l3离开范围删除,这将调用delete [] titulo_用于已删除的指针:

将其传递给释放函数(双重删除(是未定义的行为

因此,您的问题不是,;,而是因不遵循 3 法则而导致的双重删除。

如果可以的话,与其建议你

创建一个复制构造函数和复制赋值运算符,不如建议你取消Libro并在"配对"中使用string,你的代码会像这样简单:

pair<string, int> l1 = make_pair("Fundamentos de C++"s, 474), l2 = make_pair("Por Fin: C ISO"s, 224), l3;

这当然需要你显式输出每个成员,例如:

cout << l1.first << " tiene " << l1.second << " paginasn" << l2.first << " tiene " << l2.second << " paginasn" << l3.first << " tiene " << l3.second << " paginasn";

现场示例