【问题标题】:implementing a copy constructor实现复制构造函数
【发布时间】:2010-11-03 15:03:21
【问题描述】:

我有以下类定义,它需要一个复制构造函数,以便进行深度复制以复制原始指针。任何人都可以建议如何最好地做到这一点?

对 XML 使用 xerces-c++

class XMLDocument 
 {
 private:
  typedef std::vector<XML::XMLNode> v_nodes;
 public:
  XMLDocument::XMLDocument();
  XMLDocument::XMLDocument(const XMLDocument& copy); 
  XMLDocument::~XMLDocument();

  XMLDocument& operator=(XMLDocument const& rhs);

  void CreateDocument(const std::string& docname);
  void AddChildNode(XMLNode& node);
  void RemoveNode(XMLNode& node);
  void AddNodeValue(XMLNode& node, const std::string& value);
  void AddNodeValue(XMLNode& node, int value);
  void AddNodeValue(XMLNode& node, double value);
  void AddNodeValue(XMLNode& node, float value);
  std::string GetXMLAttributes();
  std::string GetXMLAttribute(const std::string& attrib);
  std::string GetXMLNodeText(XML::XMLNode& node);
  std::string DumpToString();
  XMLNode GetXPathNode(const std::string xpathXpression);
  XMLNode GetNode(const XMLNode &currentnode);

  typedef v_nodes::iterator nodes_iterator;
  nodes_iterator begin()
  {
   nodes_iterator iter;
   iter = xmlnodes.begin();

   return iter;
  }
  nodes_iterator end()
  {
   nodes_iterator iter;
   iter = xmlnodes.end();

   return iter; 
  }


 private:
  v_nodes xmlnodes;

  bool InitializeXML();
  DOMImplementation* impl; //Abstract
  DOMDocument* document; //Abstract
  DOMElement* rootelement; //Abstract

 };

DOMDocument 是调用函数创建的,也是 DOMElement。所以我不能只在这些指针上调用 new。

不确定我是否只是从字面上重新创建所有这些对象?

例子:

document = impl->createDocument(0, "mydoc", 0);

谁投了反对票却没有给出理由???

【问题讨论】:

  • 你可能应该在你的问题中提到你正在使用这个而不是你自己的类:xerces.apache.org/xerces-c/apiDocs-3/…
  • 有问题的类是否有某种 clone() 接口?如果没有,如果你想复制对象层次结构,你可能是 SOL(这意味着你必须手动完成,要么自己遍历节点,要么以某种方式序列化和反序列化文档)
  • 我看不到克隆,SOL是什么意思?
  • 请注意,自从我使用它已经有几年了...当心 Xerces 的内存泄漏,并非常小心如何使用它。我怀疑缺少的复制构造函数与内存泄漏有关。

标签: c++ copy-constructor


【解决方案1】:

此页面肯定会有所帮助:
http://icu-project.org/docs/papers/cpp_report/the_anatomy_of_the_assignment_operator.html

请注意,它们是编写复制构造函数和赋值运算符之间的区别,但本文也讨论了这一点。

【讨论】:

【解决方案2】:

编写复制构造函数始终是为每个成员变量做“正确的事”。如果没有看到您的 DOMImplementation 等的 API 文档,很难在这里说“正确的事情”是什么。也许他们有一个复制构造函数,或者一个进行深层复制的函数。也许您需要语义上的深拷贝(例如,对于DOMImplementation)。

底线,如果没有看到你肯定在身边的 API 文档就很难说...

编辑:所以您使用的是 Xerces-C。你之前没有告诉我们...

编辑2:让我们看看,然后...

据我所知,Xerces-C API 确实提供任何“简单”的复制文档对象的方法。 AFAICT,您必须创建一个全新的文档 (impl-&gt;createDocument()),然后手动复制所有属性和子节点。

这太尴尬了,我会提出一个问题“为什么我要复制我的XMLDocument 对象,无论如何?在语义层面上它甚至有意义吗?”。 (个人经验:如果在使用使用良好的 API 时事情变得丑陋,那么您可能做错了什么,因为否则会有一个简单的方法。XML 不是我的强项,所以我已经超出了我的深度在这里。)

【讨论】:

  • 这个类没有复制构造函数。
  • @DevSolar:传递这个 XMLDocument 对象并从函数中按值返回它怎么样?那么我应该总是返回一个指针吗?还是 smart_ptr?
  • @Tony:我真的不明白你想在这里做什么。 Xerces-C API 的包装器? Xerces-C 通过指针处理DOMDocument 对象,并且不允许(轻松)复制DOMDocuments。除非您有特定的想法(以及实现它的技能),否则您应该注意这一点,而不是试图“强迫”它采取不同的行为。
  • @DevSolar,我只是想将我在整个程序中需要的标准 XML 事情的复杂性封装在一个类中,并且只使用我需要的 xerces 中的位。
  • 然后我的包装器可以在我的程序的其余部分使用,如果有人决定更改要使用的 XML 库,整个程序不会受到影响。
【解决方案3】:

Devsolar 关于复制构造函数是正确的。听从他的建议。

此外,您真的不应该复制 DOM 结构。我使用 XML 时的标准过程是编写一个处理程序,该处理程序从 DOM/SAX 获取数据并基于该结构构建一个本机对象。一旦你读完所有你应该在内存中构建的 DOM/SAX 元素:

  1. 一种数据结构,包含您需要的 XML 中的所有数据。
  2. 从 XML 构建但与 XML 分离的对象。您在应用程序中使用此对象。将来您很可能会将此对象序列化为到 xml

这样你就不需要复制 DOM。您改为构建本机对象来表示数据。请记住,您希望将应用程序与 XML 分离。如果将来您决定使用二进制序列化怎么办?

【讨论】:

  • 抱歉,删除了复制构造函数的评论……它并不总是正确的,我认为这不是一个好的一般建议。
【解决方案4】:

如果您使用的库可以实现您想要的深度复制,那么解决方法是确保您的类XMLDocument 的每个拥有数据成员知道如何复制自己(使用自己的复制构造函数)。对于每个数据成员的类型,以此类推。在实践中,这意味着从头开始定义可复制的包装器类型。

注意准确定义拥有的(要复制的)和不拥有的(存在于别处并且只是被引用的)。

这种分层包装的主要原因是您希望 C++ 的自动销毁在某个部分的某些复制失败时启动。但它也大大简化了事情。当您深入到组成部分的最低级别时,您可能会获得有关复制这样一个最小部分的更好建议。

干杯,

【讨论】:

    【解决方案5】:

    我建议稍微重新考虑所有权规则。如果您想进行深度复制,您可能正在尝试解决哪个变量拥有其他变量的内存。在您的情况下,您似乎关心拥有 v_nodes 和 DOM 相关变量的 XMLDocument 的每个实例。

    解决潜在问题的另一种方法是将实例变量包装在智能指针中。

    这样,每次复制构造 XMLDocument 时,您只是在增加每个 ivars 的引用计数。每次调用 XMLDocument 实例的 dtor 时,引用计数都会递减。实质上,您将每个 XMLDocument 实例的生命周期与其 ivars 分离。相反,它是拥有它的引用计数。

    我不是 xerces 方面的专家,但值得查看各种智能 ptr 实现,例如boost 库。

    【讨论】:

      猜你喜欢
      • 2012-08-24
      • 2011-04-08
      • 1970-01-01
      • 2012-06-22
      • 2012-01-28
      • 2012-01-08
      • 1970-01-01
      • 2018-09-03
      相关资源
      最近更新 更多