复制 ctor 和赋值运算符中是不是存在语义稍有不同的问题?
Posted
技术标签:
【中文标题】复制 ctor 和赋值运算符中是不是存在语义稍有不同的问题?【英文标题】:Any gotchas in copy ctor and assignment operator having slightly different semantics?复制 ctor 和赋值运算符中是否存在语义稍有不同的问题? 【发布时间】:2011-01-13 16:11:16 【问题描述】:请看下面的代码,告诉我以后会不会出问题,如果会,如何避免。
class Note
int id;
std::string text;
public:
// ... some ctors here...
Note(const Note& other) : id(other.id), text(other.text)
void operator=(const Note& other) // returns void: no chaining wanted
if (&other == this) return;
text = other.text;
// NB: id stays the same!
...
;
简而言之,我希望复制构造函数创建对象的精确副本,包括其(数据库)ID 字段。另一方面,当我分配时,我只想复制数据字段。 但我有一些担忧,因为通常复制 ctor 和 operator= 具有相同的语义。
id 字段仅供 Note 及其朋友使用。对于所有其他客户端,赋值运算符确实会创建一个精确的副本。用例:当我想编辑一个笔记时,我使用复制ctor创建一个副本,编辑它,然后在管理笔记的笔记本类上调用保存:
Note n(notebook.getNote(id));
n = editNote(n); // pass by const ref (for the case edit is canceled)
notebook.saveNote(n);
另一方面,当我想创建一个与现有笔记内容相同的全新笔记时,我可以这样做:
Note n;
n = notebook.getNote(id);
n.setText("This is a copy");
notebook.addNote(n);
这种方法可行吗?如果不是,请指出可能的负面后果是什么!非常感谢!
【问题讨论】:
【参考方案1】:如果您想要的语义与赋值运算符的预期不匹配,请不要使用它。相反,通过声明私有 operator=
来禁用它,并定义一个函数,其名称可以明确发生了什么,例如 copyDataFields
。
【讨论】:
是否可以有一个公共副本 ctor 但私有 op=? @Alex:是的。这意味着一旦你有一个完全初始化的Note
,它就不能被分配。如果它想要数据,它将使用copyDataFields
方法。它仍然可以构造成匹配另一个音符:Note othernote(firstNote);
【参考方案2】:
虽然这可能适用于您的具体情况,但我一般不会推荐它。
诸如 STL 之类的库希望复制构造函数和赋值运算符能够“像他们应该做的那样”工作。如果您违反了 C++ 语义,那么您可能会发现对象的 STL 容器无法正常工作。 STL 将在不同的情况下调用您的复制构造函数和赋值运算符,具体取决于容器。
当您的代码没有按照您的想法执行时,很容易完全混淆。
【讨论】:
【参考方案3】:从技术上讲,它是可行的,并且在技术上可行,但我不会那样做。 我看到的问题是:
您更改了 C++ 群体已知的赋值运算符的“自然”语义。
复制构造和赋值这两个孪生操作由于语义不同而不一致。
该解决方案容易出错,因为即使看起来像是赋值,也很容易意外调用复制构造函数。如果程序员这样写你的第二个用例:
Note n = notebook.getNote(id);
然后调用复制构造函数,不是赋值,所以你得到n
作为与预期不同的对象。
为什么不让你的意图清晰明确:
Note& Notebook::editNote(int id);
Note Notebook::createNote(int id);
【讨论】:
我不想直接暴露一个Note进行编辑,我想要一种“复制、编辑、替换原始”的行为。 我几乎看不出“复制、编辑、替换原件”和“获取原件、编辑”之间有什么区别以上是关于复制 ctor 和赋值运算符中是不是存在语义稍有不同的问题?的主要内容,如果未能解决你的问题,请参考以下文章
依赖项没有复制 ctor 或赋值运算符时的 C++ 初始化程序列表
删除copy-ctor和copy-assignment - public、private还是protected?
C++ 中类的默认成员函数的问题(构造函数、析构函数、运算符 =、复制构造函数)(默认 ctor、dtor、复制 ctor)