英文:
An instance variable, which is a pointer to an array item, doesn't point to that item anymore after the object is passed to a class constructor
问题
我有一个简单的示例,我可以在其中复现我遇到的问题。
#include <iostream>
class A {
public:
long arr[3] = {0x10, 0x20, 0x30};
long *item1 = &arr[0], *item2 = &arr[1], *item3 = &arr[2];
A();
};
class B {
public:
A a;
B(A);
};
A::A() {}
B::B(A param) {
a = param;
}
int main() {
A a = A();
B b = B(a);
std::cout << a.arr[0] << std::endl;
std::cout << a.item1 << std::endl;
std::cout << b.a.arr[0] << std::endl;
std::cout << b.a.item1 << std::endl;
}
如果我将a
传递给类B
的构造函数,那么a
的实例变量,它们被设置为指向arr
的第i个元素,将不再指向那个元素。我不想将a
的引用传递给B类的构造函数,我想像我目前正在做的那样传递一个副本。
我希望发生的事情:
&a.arr[0]
和a.item1
具有相同的值,&b.a.arr[0]
和b.a.item1
具有相同的值。
实际发生的事情:
&a.arr[0]
,a.item1
和b.a.item1
具有相同的值,而&b.a.arr[0]
具有不同的值。
如果我将item1
设置为arr[0]
的内存地址,那么为什么在传递给类B
之后item1
和arr[0]
不再指向同一物体?我当然会期望&a.arr[0]
和&b.a.arr[0]
具有不同的值,但我也会期望&a.arr[0]
和a.item1
具有相同的值,&b.a.arr[0]
和b.a.item1
具有相同的值。为什么这不会发生,我该如何实现这一点?再次强调,我不想将a
的引用传递给B
的构造函数,因为我想修改b.a
并返回修改后的版本,而不影响原始的a
。
英文:
I have a minimal example here where I can reproduce the issue I'm facing.
#include <iostream>
class A {
public:
long arr[3] = {0x10, 0x20, 0x30};
long *item1 = &arr[0], *item2 = &arr[1], *item3 = &arr[2];
A();
};
class B {
public:
A a;
B(A);
};
A::A() {}
B::B(A param) {
a = param;
}
int main() {
A a = A();
B b = B(a);
std::cout << &a.arr[0] << std::endl;
std::cout << a.item1 << std::endl;
std::cout << &b.a.arr[0] << std::endl;
std::cout << b.a.item1 << std::endl;
}
If I pass a
into the constructor for class B
, then a
's instance variables, which were set to point to the ith element of arr
, no longer point to that. I do not want to pass in a reference of a
into the constructor for B, I want to pass in a copy as I am currently doing.
What I expect to happen:
&a.arr[0]
and a.item1
have the same value, and &b.a.arr[0]
and b.a.item1
have the same value.
What actually happens:
&a.arr[0]
, a.item1
, and b.a.item1
have the same value, while &b.a.arr[0]
has a different value.
If I set item1
to be the memory address of arr[0]
, then how come item1
and arr[0]
don't point to the same thing after passing it in to class B
? I would expect &a.arr[0]
to have a different value than &b.a.arr[0]
of course, but I would also expect &a.arr[0]
and a.item1
to have the same value, and &b.a.arr[0]
and b.a.item1
to have the same value. Why is this not happening, and how do I make that happen? Again, I don't want to pass a reference to a
into the constructor for B
, because I would like to modify b.a
and return the modified version without affecting the original a
.
答案1
得分: 1
当你复制A的实例时,你也复制了所有的指针。因此,新实例中的指针都指向被复制的实例,而不是包含指针的实例。
如果你希望每个A的实例中的指针始终指向该A实例,你需要编写一个显式的复制构造函数(以及复制赋值运算符,如果需要的话),来实现这一点。你可能还希望为不同的情况编写移动构造函数(和赋值运算符),但在这种情况下(因为你的数组元素只是long
),这并不是特别有用。
A::A(const A &a) {
std::copy(std::begin(a.arr), std::end(a.arr), std::begin(arr));
item1 = &arr[0];
item2 = &arr[1];
item3 = &arr[2];
}
A &A::operator=(const A &a) {
std::copy(std::begin(a.arr), std::end(a.arr), std::begin(arr));
return *this;
}
英文:
When you copy an instance of A, you also copy all the pointers. So the pointers in the new instance all point at the instance copied from, not the the instance containing the pointers.
If you want to pointers in each instance of A to always point at that instance of A, you need to write an explicit copy constructor (and copy assignment, if you want that), that does that. You may also want a move constructor (and assignment) for different situations, but in this case (as your array elements are just long
s) it's not particularly useful.
A::A(const A &a) {
std::copy(std::begin(a.arr), std::end(a.arr), std::begin(arr));
item1 = &arr[0];
item2 = &arr[1];
item3 = &arr[2];
}
A &A::operator=(const A &a) {
std::copy(std::begin(a.arr), std::end(a.arr), std::begin(arr));
return *this;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论