你能用复制赋值运算符创建一个新实例吗?
Can you create a new instance with the copy assignment operator?
我正在研究 C++ 中的复制赋值运算符,我想知道如果对象为 null 是否有创建新实例的方法。
class Person {
public:
Person(string name) { pName_ = new string(name); }
~Person() { delete pName_; }
Person(const Person& rhs) {
if (pName_ != NULL) delete pName_;
pName_ = new string(*(rhs.pName()));
}
Person& operator=(const Person& rhs) {
cout << "begin copy..." << endl;
if (this == NULL) {
Person* p = new Person(rhs);
cout << "end copy null..." << endl;
return *p; // Not working?
}
delete pName_;
pName_ = new string(*(rhs.pName()));
cout << "end copy..." << endl;
return *this;
};
string* pName() const { return pName_; }
void printName() { cout << *pName_ << endl; }
private:
string* pName_;
};
int main() {
Person *a = new Person("Alex");
Person *b = new Person("Becky");
Person *c = NULL;
*b = *a; // copy works
*c = *a; // copy doesn't
if (a != NULL) a->printName(); // Alex
if (a != NULL) delete a;
if (b != NULL) b->printName(); // Alex
if (b != NULL) delete b;
if (c != NULL) c->printName(); // NULL
if (c != NULL) delete c;
return 0;
}
这是输出:
begin copy...
end copy...
begin copy...
end copy null...
Alex
Alex
我是否可以在我的代码中更改某些内容以使其工作,或者这是我什至不应该尝试尝试的内容?
你给出的代码各种错误,需要重写。
您正在通过取消引用的 NULL 指针调用未正确实现的复制赋值运算符,这是未定义的行为。复制赋值运算符被定义为仅使用有效对象调用,并且必须将值从一个对象复制到另一个对象,并且 return 对复制到的对象的引用。你没有那样做。
回答你的问题,不,当this
为NULL时,复制赋值运算符不能创建新对象。对于初学者,如果 this
为 NULL,那么您的代码中有一个错误需要修复。但是即使 this
为 NULL,运算符也无法更新调用者的指针(假设首先使用了指针)以指向新的对象实例。 this
只是一个 compiler-generated 参数,包含被调用对象的内存地址,它不是调用者用于调用运算符的原始指针。因此,如果运算符确实在堆上分配了一个新对象,则该对象将在运算符退出时泄漏,因为调用者将没有指向该对象的指针以稍后释放它。
您的代码的正确版本应该更像这样:
class Person {
public:
Person(const string &name) : pName_(name) {}
Person& operator=(const Person& rhs) {
// if you remove these output statements then
// this entire operator can be removed...
cout << "begin copy..." << endl;
if (this != &rhs) {
pName_ = rhs.pName();
cout << "non self copied..." << endl;
}
cout << "end copy..." << endl;
return *this;
}
string pName() const {
return pName_;
}
void printName() const {
cout << pName_ << endl;
}
private:
string pName_;
};
int main() {
Person *a = new Person("Alex");
Person *b = new Person("Becky");
Person *c = NULL;
*b = *a;
//*c = *a; UNDEFINED BEHAVIOR!
if (a) {
a->printName();
delete a;
}
if (b) {
b->printName();
delete b;
}
if (c) {
c->printName();
delete c;
}
return 0;
}
我正在研究 C++ 中的复制赋值运算符,我想知道如果对象为 null 是否有创建新实例的方法。
class Person {
public:
Person(string name) { pName_ = new string(name); }
~Person() { delete pName_; }
Person(const Person& rhs) {
if (pName_ != NULL) delete pName_;
pName_ = new string(*(rhs.pName()));
}
Person& operator=(const Person& rhs) {
cout << "begin copy..." << endl;
if (this == NULL) {
Person* p = new Person(rhs);
cout << "end copy null..." << endl;
return *p; // Not working?
}
delete pName_;
pName_ = new string(*(rhs.pName()));
cout << "end copy..." << endl;
return *this;
};
string* pName() const { return pName_; }
void printName() { cout << *pName_ << endl; }
private:
string* pName_;
};
int main() {
Person *a = new Person("Alex");
Person *b = new Person("Becky");
Person *c = NULL;
*b = *a; // copy works
*c = *a; // copy doesn't
if (a != NULL) a->printName(); // Alex
if (a != NULL) delete a;
if (b != NULL) b->printName(); // Alex
if (b != NULL) delete b;
if (c != NULL) c->printName(); // NULL
if (c != NULL) delete c;
return 0;
}
这是输出:
begin copy...
end copy...
begin copy...
end copy null...
Alex
Alex
我是否可以在我的代码中更改某些内容以使其工作,或者这是我什至不应该尝试尝试的内容?
你给出的代码各种错误,需要重写。
您正在通过取消引用的 NULL 指针调用未正确实现的复制赋值运算符,这是未定义的行为。复制赋值运算符被定义为仅使用有效对象调用,并且必须将值从一个对象复制到另一个对象,并且 return 对复制到的对象的引用。你没有那样做。
回答你的问题,不,当this
为NULL时,复制赋值运算符不能创建新对象。对于初学者,如果 this
为 NULL,那么您的代码中有一个错误需要修复。但是即使 this
为 NULL,运算符也无法更新调用者的指针(假设首先使用了指针)以指向新的对象实例。 this
只是一个 compiler-generated 参数,包含被调用对象的内存地址,它不是调用者用于调用运算符的原始指针。因此,如果运算符确实在堆上分配了一个新对象,则该对象将在运算符退出时泄漏,因为调用者将没有指向该对象的指针以稍后释放它。
您的代码的正确版本应该更像这样:
class Person {
public:
Person(const string &name) : pName_(name) {}
Person& operator=(const Person& rhs) {
// if you remove these output statements then
// this entire operator can be removed...
cout << "begin copy..." << endl;
if (this != &rhs) {
pName_ = rhs.pName();
cout << "non self copied..." << endl;
}
cout << "end copy..." << endl;
return *this;
}
string pName() const {
return pName_;
}
void printName() const {
cout << pName_ << endl;
}
private:
string pName_;
};
int main() {
Person *a = new Person("Alex");
Person *b = new Person("Becky");
Person *c = NULL;
*b = *a;
//*c = *a; UNDEFINED BEHAVIOR!
if (a) {
a->printName();
delete a;
}
if (b) {
b->printName();
delete b;
}
if (c) {
c->printName();
delete c;
}
return 0;
}