为什么程序在构造函数之后停止?
Why program stops after constructor?
我正在学习运算符重载,我在某处读到,当您将 r 值分配给对象时,它会创建一个临时对象,但该程序在为 r 值调用构造函数后停止。
Class.h
class Foo{
int *num;
public :
Foo(int x);
Foo& operator=(Foo &&rhs);
Foo& operator=(const Foo &rhs);
Foo(Foo &f);
Foo(Foo &&f);
void set(int x);
void show();
~Foo();
};
Class.cpp
#include <iostream>
#include "class.h"
#include <cstring>
Foo::Foo(int x){
num = new int;
*num = x;
std::cout << "Constructor for " << *num << std::endl;
};
Foo::~Foo(){
std::cout << "Destructor for " << *num << std::endl;
delete num;
}
void Foo::show(){
std::cout << *num << std::endl;
}
void Foo::set(int x){
*num = x;
std::cout << "INSIDE SETTER" << std::endl;
}
Foo& Foo::operator=(Foo &&rhs){
num = rhs.num;
rhs.num = nullptr;
return *this;
}
Foo& Foo::operator=(const Foo &rhs){
*num = *rhs.num;
return *this;
}
Foo::Foo(Foo &f){
num = new int;
*num = *f.num;
std::cout << "Copy constructor used " << std::endl;
}
Foo::Foo(Foo &&f)
: num{f.num}{
std::cout << "Move constructor used " << std::endl;
f.num = nullptr;
}
int main(){
Foo f1(10);
Foo f2(20);
Foo f3(30);
f1.show();
f2.show();
f3.show();
f1 = 60;
f1.show();
f2.show();
f3.show();
return 0;
}
程序在调用构造函数 60 后停止。
输出
10
的构造函数
20
的构造函数
30
的构造函数
10
20
30
60
的构造函数
[完成] 在 1.458 秒内以代码 =3221225477 退出
当我使用 char *str 而不是 int *num 时它有效
你的问题出在析构函数中。它尝试访问 *num
,但将赋值运算符集 num
移动到 nullptr
.
保护日志记录以防止 nullptr
(不需要保护 delete
,因为它保证在空指针上正常工作):
Foo::~Foo(){
if (num) {
std::cout << "Destructor for " << *num << std::endl;
} else {
std::cout << "Destructor for null pointer" << std::endl;
}
delete num;
}
或者在移动分配中使用交换并让 rhs
最终删除它(这也将修复内存泄漏:你永远不会删除 num
的旧值)
Foo& Foo::operator=(Foo &&rhs)
{
std::swap(num, rhs.num);
return *this;
}
swap
解的输出:
Constructor for 10
Constructor for 20
Constructor for 30
10
20
30
Constructor for 60
Destructor for 10
60
20
30
Destructor for 30
Destructor for 20
Destructor for 60
我正在学习运算符重载,我在某处读到,当您将 r 值分配给对象时,它会创建一个临时对象,但该程序在为 r 值调用构造函数后停止。
Class.h
class Foo{
int *num;
public :
Foo(int x);
Foo& operator=(Foo &&rhs);
Foo& operator=(const Foo &rhs);
Foo(Foo &f);
Foo(Foo &&f);
void set(int x);
void show();
~Foo();
};
Class.cpp
#include <iostream>
#include "class.h"
#include <cstring>
Foo::Foo(int x){
num = new int;
*num = x;
std::cout << "Constructor for " << *num << std::endl;
};
Foo::~Foo(){
std::cout << "Destructor for " << *num << std::endl;
delete num;
}
void Foo::show(){
std::cout << *num << std::endl;
}
void Foo::set(int x){
*num = x;
std::cout << "INSIDE SETTER" << std::endl;
}
Foo& Foo::operator=(Foo &&rhs){
num = rhs.num;
rhs.num = nullptr;
return *this;
}
Foo& Foo::operator=(const Foo &rhs){
*num = *rhs.num;
return *this;
}
Foo::Foo(Foo &f){
num = new int;
*num = *f.num;
std::cout << "Copy constructor used " << std::endl;
}
Foo::Foo(Foo &&f)
: num{f.num}{
std::cout << "Move constructor used " << std::endl;
f.num = nullptr;
}
int main(){
Foo f1(10);
Foo f2(20);
Foo f3(30);
f1.show();
f2.show();
f3.show();
f1 = 60;
f1.show();
f2.show();
f3.show();
return 0;
}
程序在调用构造函数 60 后停止。
输出
10
的构造函数
20
的构造函数
30
的构造函数
10
20
30
60
的构造函数
[完成] 在 1.458 秒内以代码 =3221225477 退出
当我使用 char *str 而不是 int *num 时它有效
你的问题出在析构函数中。它尝试访问 *num
,但将赋值运算符集 num
移动到 nullptr
.
保护日志记录以防止 nullptr
(不需要保护 delete
,因为它保证在空指针上正常工作):
Foo::~Foo(){
if (num) {
std::cout << "Destructor for " << *num << std::endl;
} else {
std::cout << "Destructor for null pointer" << std::endl;
}
delete num;
}
或者在移动分配中使用交换并让 rhs
最终删除它(这也将修复内存泄漏:你永远不会删除 num
的旧值)
Foo& Foo::operator=(Foo &&rhs)
{
std::swap(num, rhs.num);
return *this;
}
swap
解的输出:
Constructor for 10
Constructor for 20
Constructor for 30
10
20
30
Constructor for 60
Destructor for 10
60
20
30
Destructor for 30
Destructor for 20
Destructor for 60