如何:在没有适当的默认构造函数的情况下复制类的实例;有没有默认构造函数的成员?

时间:2015-08-31 06:26:33

标签: c++

var oReq = getXMLHttpRequest();
if (oReq != null) {
    oReq.open("POST", "http://www.example.com/index.php?r=user/create-mobile-user", true);
    oReq.onreadystatechange = function handler() {
        if (oReq.readyState == 4) {
            if (oReq.status == 200) {
                window.google_trackConversion ({
                    google_conversion_id: 946425313,
                    google_conversion_language: "en",
                    google_conversion_format: "3",
                    google_conversion_color: "ffffff",
                    google_conversion_label: "7P62CPrGtl4Q4ZulwwM",
                    google_remarketing_only: false
                });
                window.location.href = "http://www.example.com/booking";
            }
        }
    }
}

阅读rule of three以找出将类的实例复制到向量中的问题。

所以问题是我们在循环中生成实例:

// B doesn't have a default constructor.
class A {
  public:
  A(Important resource) : b(resource) {}
  B b;
};

从我们看到的Valgrind,它闻起来像复制构造函数正在搞砸了。 当我们将代码更改为:

std::vector<A> some_vector(0);
for (int i = 0; i < 7; i++)
  some_vector.push_back(A(resources[i]));

问题得到缓解。虽然不需要,但不喜欢这样做。所以我在想,当复制构造函数试图在没有正确的默认构造函数的情况下复制一个类时,它将如何知道该做什么?

1 个答案:

答案 0 :(得分:3)

对于要在C ++中推入std :: vector的类型T的元素,

  

T must meet the requirements of CopyAssignable and CopyConstructible.

这意味着它必须具有工作移动或复制构造函数,这将在创建新对象时使用。它通常不需要默认构造函数,但某些操作可能需要它,例如, resize

作为您示例中的资源,它应该是不可复制的,但可能是可移动的。如果B没有正确的拷贝构造函数,您将得到资源的副本,析构函数将多次释放资源(例如,释放内存或关闭文件)。

对于资源,常见的模式是使用RAII,例如std :: unique_pointer for memory。

PS:从C ++ 11开始,有一种新类型的构造函数/赋值运算符。三条规则现在成为五条规则,但最好不要在不处理资源处理类时编写复制或赋值构造函数。只有这些需要实现操作,其他类只能使用它。这是rule of zero,这是我建议坚持的。同样,std::unique_pointer就是一个很好的例子。您的类可以只使用unique_ptrshared_ptr,而不是编写移动/复制构造函数,并且会处理内存管理。