复制构造函数和运算符=是必须的
Are copy constructor and operator= a must?
我在某处读到:
具有指针数据成员的每个类都应包含以下成员函数:
- 析构函数
- 复制构造函数,
- 运算符 =(赋值(
这是真的吗?如果复制对象没有意义怎么办?
如果相关指针数据成员指向不需要复制或无法更改的内容,该怎么办?
我举一个具体的例子:一个人出生在某个日期;Date 是一个对象,它保存诸如一天有多长或一周中的哪一天等值。我不想"复制"一个人,但即使我必须这样做,他们不应该指向同一个 Date 对象吗?
如果这是真的,为什么?
指针数据成员可能意味着不同的东西。如果指针只是一个观察指针(指向在其他地方管理的对象(,那么编译器生成的复制构造函数和运算符(它们只是复制指针的值(绝对没有问题。这里的潜在问题是指针的寿命可能超过对象,使其成为悬空指针。
如果它是指向堆上分配并由 this
管理的内存的指针,则必须确保正确完成复制。简单地不实现 copy(构造函数和运算符(不是一种选择,因为编译器会自动创建它们,而这些很可能不会做你想要的。从 2011 年开始(使用 C++11(,您当然可以=delete
复制和/或实现移动(构造函数和运算符(。
但是,最明智的做法是避免使用此类指针,以支持数据管理类,例如std::unique_ptr
或std::vector
等。
"应该"这个词和"必须"这个词有很大的区别。 当我读到你提出的案文时,它的意思是我应该强烈考虑做这三件事,而不是说这是绝对必要的。 逻辑、经验和可行性将胜过诸如适当时和地点的指导方针。
话虽如此,如果有意义,在你的课堂上有这三件事总是好的。
在您的日期示例中,这不应该是一个指针。如果是指针,
你得到一个临时的,或者一个副本,析构函数是做什么的?叫
delete
日期对象?如果您两次致电delete
(您现在有 2
个对象(在同一指针上,其未定义的行为。
关于不该做什么的例子:
class Persson
{
public:
Persson( string name, string date )
: m_name(name)
{
m_date = new Date;
ParseDate( *m_date, date );
}
~Persson()
{
delete m_date;
}
private:
string m_name;
Date* m_date;
};
如果您曾经复制过Persson
这将出错。
很容易获得副本,临时的无处不在。
一种可能性是指针生存期由其他人管理,
在这种情况下,指针可以更多地被视为句柄,那么没关系
定义复制构造函数、分配运算符和析构函数。
除非对象生存期由其他人管理,否则您应该
根本不真正使用指针,要么直接使用值,要么使用智能指针。
不太糟糕的例子:
class Persson
{
public:
Persson( string name, string date )
: m_name(name)
{
m_date = make_shared<Date>();
ParseDate( *m_date.get(), date );
}
private:
string m_name;
shared_ptr<Date> m_date;
};
更好的例子
class Persson
{
public:
Persson( string name, string date )
: m_name(name)
{
ParseDate( m_date, date );
}
private:
string m_name;
Date m_date;
};
始终在C++中使用值语义,它就是为此而生的。
看看零法则
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 通过继承类使用来自不同命名空间的运算符
- 向量范数的c++中的||运算符
- 在使用累加时,C++中的运算符+不匹配
- 如何使基类的运算符对基类的可变参数数可见(请参阅下面的代码)?
- 类中 c++ 的运算符 + 重载
- 如何理解新的运算符重载?
- 错误 C2679:二进制"<<":未找到采用类型 'std::string_view' 的右侧操作数的运算符(或者没有可接受的转换)
- 向量保持复数的运算符重载
- -> if (C++) 中的运算符
- 为什么字符串比较的 == 运算符相对于任一字符串长度线性时间(似乎)?
- 重载 MPI 中的运算符 ()
- 为什么我在初始化b2World时必须使用新的运算符?-方框2d
- 重载必须返回对对象的引用的运算符
- 重载的"运算符+"必须是一元或二进制运算符错误
- 复制构造函数和运算符=是必须的
- 错误,*的运算符必须是指针
- 为什么我必须调用运算符<<作为 SFINAE 使用void_t的方法?
- 什么意思是"错误:重载的'运算符*'必须至少有一个类或枚举类型的参数"
- 错误:重载的"运算符<<"必须是二元运算符(有 3 个参数)