复制语义和比较

Posted

技术标签:

【中文标题】复制语义和比较【英文标题】:Copy Semantics and Comparison 【发布时间】:2012-06-20 22:41:17 【问题描述】:

有没有办法将 YAML::Node 对象中所有值的副本复制到新对象(即克隆)中?还有一种方法可以通过节点中的值来测试两个 YAML::Node 对象之间的相等性(即 .equals() 函数而不是 .is() 函数)?

考虑以下示例:

YAML::Node a;
a["x"][1]["y"][2]["z"][3] = 1;
std::cout << "A_____\n" << a << "\n\n\n\n";

std::cout << "Test 1\n";
YAML::Node z = a["x"][1]["y"][2]["z"];
z[3] = 2;
std::cout << "Z_____\n" <<  z << "\n";
std::cout << "A_____\n" <<  a << "\n\n\n\n";

std::cout << "Test 2\n";
YAML::Node b = a;
b["x"][1]["y"][2]["z"][3] = 3;
std::cout << "B_____\n" <<  b << "\n";
std::cout << "Z_____\n" <<  z << "\n";
std::cout << "A_____\n" <<  a << "\n\n\n\n";

std::cout << "Test 3\n";
YAML::Node c;
c["x"][1]["y"][2]["z"][3] = 3;
std::cout << "C_____\n" <<  c << "\n";
std::cout << "A_____\n" <<  a << "\n";
std::cout << "a == c: " <<  bool(a==c) << "\n";
std::cout << "z == a[\"x\"][1][\"y\"][2][\"z\"]: "
            <<  bool(z == a["x"][1]["y"][2]["z"]) << "\n\n";

运行时输出以下内容:

A_____
x:
  1:
    y:
      2:
        z:
          3: 1



Test 1
Z_____
3: 2
A_____
x:
  1:
    y:
      2:
        z:
          3: 2



Test 2
B_____
x:
  1:
    y:
      2:
        z:
          3: 3
Z_____
3: 3
A_____
x:
  1:
    y:
      2:
        z:
          3: 3



Test 3
C_____
x:
  1:
    y:
      2:
        z:
          3: 3
A_____
x:
  1:
    y:
      2:
        z:
          3: 3
a == c: 0
z == a["x"][1]["y"][2]["z"]: 1

在测试1中,修改z也会修改a["x"][1]["y"][2]["z"]的值,同样在测试2中,修改b相当于修改a。这些复制语义是否被视为 API 的一部分(即它们将来可能会改变)?我希望能够编写诸如z = getZ() 之类的代码,并让getZ() 返回a["x"][1]["y"][2]["z"](“x”、“y”和“z”的名称将来可能会更改)。修改z 将修改a,如示例所示。

另外,有没有办法将a 的克隆复制到一个新对象b 中,这样修改b 就不会同时修改a

在test3中,c中的值与a中的值相同。有什么方法可以为 YAML::Node 对象做a.equals(c),以测试两个节点中的值是否都相同?在示例中,a.equals(c) 为真。

【问题讨论】:

【参考方案1】:

要深拷贝一个节点:

YAML::Node node = /* ... */;
YAML::Node other = Clone(node);

(现在已实现;您可以看到旧的bug report。)

当前行为是有意的(换句话说,典型的“复制”只是设置身份),不会改变。

关于相等性,一般来说,对于 YAML 来说,这是一个非常困难的问题。 yaml-cpp项目页面this issue有一些讨论。

【讨论】:

以上是关于复制语义和比较的主要内容,如果未能解决你的问题,请参考以下文章

堆对象自然不支持复制语义

复制 ctor 和赋值运算符中是不是存在语义稍有不同的问题?

提升变体复制语义

如果分配器提供 realloc 语义,std::vector 可以避免复制吗?

是否可以在 C++ 中将返回值移动语义与受保护的复制构造函数一起使用?

std::unique_ptr 作为参数的正确复制语义