gpt4 book ai didi

c++ - C++成功复制动态分配的obj,而无需复制ctor?

转载 作者:行者123 更新时间:2023-12-02 09:56:28 25 4
gpt4 key购买 nike

我有一类与char指针。我想知道在没有显式定义副本构造函数的情况下怎么可能进行副本构造?

我认为是因为对象已经被分配了,但是如果是这样,那为什么有人首先需要复制构造函数呢?

#include <iostream>
#include <cstring>

class Data {
public:
explicit Data(const char* newData)
:size{strlen(newData)},
data{size ? new char[size] : nullptr}
{
std::memcpy(data, newData, size);
}

friend std::ostream& operator<<(std::ostream& ost, const Data& rhs) {
for (std::size_t i = 0; i < rhs.size; i++) {
std::cout << rhs.data[i];
}
ost << "\n";
return ost;
}

~Data() {
delete[] data;
}

private:
std::size_t size;
char* data;
};

int main() {
Data data1{"data1"};
Data data2{data1}; // copy constructor
std::cout << data1;
std::cout << data2;

return 0;
}

输出:
data1
data1

复制构造函数不应该是这样吗?我经常看到这样的例子。但是由于默认构造函数已经做到了,那么我什么时候真正需要定义复制ctor?
Data(const Data& other) {
if (this != &other) {
size = other.size;
data = new char[size];
std::memcpy(data, other.data, size);
}
}

顺便说一下,我意识到代码引入了一些恶意的做法(例如,使用new而不是智能ptrs,首先不使用字符串,等等-但这只是一个练习)。

最佳答案

从C++ 11开始,如果类具有用户定义的析构函数,则不建议使用implicitly-defined copy constructor生成,但是仍然会生成。该复制构造函数将只复制sizedata,从而进行浅拷贝,而不是深表复制。这是一条通往灾难的道路,因为在原始对象及其副本被销毁时,data随后将被多次删除。

例如,如果您在Valgrind下运行原始代码,则会看到以下报告:

==9908== HEAP SUMMARY:
==9908== in use at exit: 0 bytes in 0 blocks
==9908== total heap usage: 3 allocs, 4 frees, 73,733 bytes allocated
==9908==
==9908== All heap blocks were freed -- no leaks are possible
==9908==
==9908== For counts of detected and suppressed errors, rerun with: -v
==9908== ERROR SUMMARY: 18 errors from 9 contexts (suppressed: 0 from 0)

如果希望 Data是可复制的,则必须提供一个深度复制构造函数,该构造函数分配新的存储并将数据复制到其中。您问题中的一个看起来几乎(*)很好:

==9993== HEAP SUMMARY:
==9993== in use at exit: 0 bytes in 0 blocks
==9993== total heap usage: 4 allocs, 4 frees, 73,738 bytes allocated
==9993==
==9993== All heap blocks were freed -- no leaks are possible
==9993==
==9993== For counts of detected and suppressed errors, rerun with: -v
==9993== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

如果根本不需要复制构造,则可以通过显式删除它来禁用其隐式生成:
Data(const Data&) = delete;

复制分配运算符也是如此。 implicitly-defined one不会做您想要的。 Don't forget关于它。

(*)注意 other.data可以是 nullptr,因此您在复制之前先 have to check it:

void* memcpy(void* dest, const void* src, std::size_t count);

If either dest or src is a null pointer, the behavior is undefined, even if count is zero.

关于c++ - C++成功复制动态分配的obj,而无需复制ctor?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59658165/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com