代码之家  ›  专栏  ›  技术社区  ›  Alex Jenter

copy ctor和assignment操作符中的gotchas有稍微不同的语义吗?

  •  4
  • Alex Jenter  · 技术社区  · 15 年前

    请看下面的代码,并告诉我它是否会在将来引起问题,如果是,如何避免它们。

    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字段。另一方面,当我分配时,我只想复制数据字段。 但我有一些顾虑,因为通常copy ctor和operator=具有相同的语义。

    ID字段仅由Notes及其朋友使用。对于所有其他客户机,赋值运算符确实创建了一个精确的副本。用例:当我想要编辑一个笔记时,我使用copy ctor创建一个副本,编辑它,然后调用管理笔记的notebook类上的save:

     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);
    

    这种方法可行吗?如果没有,请指出可能的负面后果是什么!谢谢!

    3 回复  |  直到 15 年前
        1
  •  9
  •   aem    15 年前

    如果您希望语义与赋值操作符所期望的不匹配,那么就不要使用它。相反,通过声明一个私有 operator= 定义一个函数,它的名称可以清楚地说明发生了什么,比如 copyDataFields .

        2
  •  4
  •   d3jones    15 年前

    虽然这可能适用于您的具体情况,但我一般不推荐它。

    像STL这样的库希望复制构造函数和赋值操作符“像预期的那样”工作。如果违反C++语义,则可能会发现对象的STL容器不能正常工作。STL将在不同的情况下调用复制构造函数和赋值运算符,具体取决于容器。

    当你的代码没有像你想象的那样执行时,很容易被完全混淆。

        3
  •  1
  •   mloskot    15 年前

    从技术上讲,这是可行的,技术上可行,但我不会那样做。 我看到的问题是:

    1. 您改变赋值运算符的“自然”语义,如C++人口数所知。

    2. 由于语义上的不同,复制构造和赋值这两种操作是不一致的。

    3. 解决方案容易出错,因为很容易意外调用 复制构造函数 即使看起来像作业。如果程序员以这种方式编写第二个用例:

      Note n = notebook.getNote(id);
      

      然后调用复制构造函数, 不分配 所以你得到 n 作为不同于预期的对象。

    为什么不让你的意图变得清晰和明确:

    Note& Notebook::editNote(int id);
    Note  Notebook::createNote(int id);
    
    推荐文章