提问人:radar101 提问时间:6/8/2022 更新时间:6/8/2022 访问量:270
C++:复制构造函数后两个对象的值都会更改
C++: Values of both objects changes after a Copy Constructor
问:
我编写了一个简单的 c++ 代码来理解复制构造函数/运算符重载的概念。代码片段如下所示。
在代码中,我正在创建一个对象,然后创建一个新对象并分配 .接下来,我调用重载来更改 和 的值。vec v2
v4
vec v2
operator[]
v4[0]
v4[1]
我的问题是,在分配这些值后,的值也发生了变化。
我不太确定这是怎么发生的。希望有人能帮我解决这个问题。vec v2
class vec {
private:
// Variable to store the number of elements contained in this vec.
size_t elements;
// Pointer to store the address of the dynamically allocated memory.
double* data;
public:
vec(size_t size) : elements{ size }, data{ new double[size] } {std::cout << "First constructor" << "\n"; };
vec(size_t size, double ival) : elements{ size }, data{ new double[size] } {
std::cout << "Second constructor" << std::endl;
for (int i = 0; i < elements; i++) {
data[i] = ival;
}
}
vec(std::initializer_list<double> iList): vec(static_cast<size_t>(iList.size())) {
std::cout << "Third constructor" << std::endl;
auto count{ 0 };
for (auto element: iList) {
data[count] = element;
count++;
}
}
/// Copy constructor that creates a copy of the vec variable 'v'.
vec(const vec& v) : elements{ v.elements }, data{ new double[v.elements] }{
std::cout << "Copy constructor " << "\n";
std::memcpy(&data, &(v.data), v.elements);
}
/// Copy assignment operator. Creates a copy of vec variable 'v'.
vec& operator=(const vec& v) {
std::cout << "Copy assignment " << "\n";
if (this != &v) {
const auto new_data{ new double[v.elements] };
delete[] data;
data = new_data;
elements = v.elements;
std::memcpy(&data, &(v.data), v.elements);
}
return *this;
}
double& operator[](size_t idx){
return this->data[idx];
}
friend std::ostream& operator<<(std::ostream& os, const vec& v) {
for (int i = 0; i < v.elements; i++) {
os << v.data[i] << "\n";
}
return os;
}
};
int main(void) {
vec v2 = {4, 5, 6};
vec v4 = v2
v4[0] = 11; // call to operator[]
v4[1] = 12; // call to operator[]
return 0;
}
答:
2赞
PaulMcKenzie
6/8/2022
#1
问题是该函数的误用:std::memcpy
std::memcpy(&data, &(v.data), v.elements);
由于 和 已经是指向数据的指针,因此获取这些指针的地址会导致这些参数使用不正确的指针值。data
v.data
另一个问题是,第三个参数应该表示要复制的字节数,而不是元素数。v.elements
正确的调用应该是:std::memcpy
std::memcpy(data, v.data, v.elements * sizeof(double));
但说了这么多,不要使用 ,而是使用 。这将适用于元素的数量,并且可以处理不可轻易复制的类型(例如):std::memcpy
std::copy
std::string
#include <algorithm>
//...
std::copy(v.data, v.data + v.elements, data);
评论
0赞
radar101
6/8/2022
嗨,PaulMcKenzie,感谢您的回复。是的,问题出在.我使用 for 循环执行了元素复制,它也有效。我尝试过并建议你,它奏效了。我可以知道是否是现代 C++ 中的推荐使用方式?std::memcpy
std::memcpy
std::copy
std::copy
1赞
PaulMcKenzie
6/8/2022
使用 ,因为编译器将(应该)默认用于 等简单类型。因此,您不会通过显式调用获得任何好处,而只会可能导致错误(例如您遇到的错误)。用于强制执行此操作的情况,例如从一个缓冲区复制到另一个缓冲区,并且源和目标属于不同的类型。std::copy
memcpy
double
memcpy
memcpy
评论
memcpy
memcpy()
std::memcpy(&data, &(v.data), v.elements);
-- 使用 ,而不是 -- 仔细阅读文档,因为最后一个参数是错误的。此外,如果这是 的向量,则使用绝对无法正常工作,即使对最后一个参数进行了“更正”。std::copy
std::memcpy
std::memcpy
std::string
std::memcpy
initializer_list