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

huangapple go评论71阅读模式
英文:

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.item1b.a.item1具有相同的值,而&b.a.arr[0]具有不同的值。

如果我将item1设置为arr[0]的内存地址,那么为什么在传递给类B之后item1arr[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 &lt;iostream&gt;

class A {
public:
	long arr[3] = {0x10, 0x20, 0x30};
	long *item1 = &amp;arr[0], *item2 = &amp;arr[1], *item3 = &amp;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 &lt;&lt; &amp;a.arr[0] &lt;&lt; std::endl;
	std::cout &lt;&lt; a.item1 &lt;&lt; std::endl;

	std::cout &lt;&lt; &amp;b.a.arr[0] &lt;&lt; std::endl;
	std::cout &lt;&lt; b.a.item1 &lt;&lt; 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:

&amp;a.arr[0] and a.item1 have the same value, and &amp;b.a.arr[0] and b.a.item1 have the same value.

What actually happens:

&amp;a.arr[0], a.item1, and b.a.item1 have the same value, while &amp;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 &amp;a.arr[0] to have a different value than &amp;b.a.arr[0] of course, but I would also expect &amp;a.arr[0] and a.item1 to have the same value, and &amp;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 longs) it's not particularly useful.

A::A(const A &amp;a) {
    std::copy(std::begin(a.arr), std::end(a.arr), std::begin(arr));
    item1 = &amp;arr[0];
    item2 = &amp;arr[1];
    item3 = &amp;arr[2];
}

A &amp;A::operator=(const A &amp;a) {
    std::copy(std::begin(a.arr), std::end(a.arr), std::begin(arr));
    return *this;
}

huangapple
  • 本文由 发表于 2023年7月18日 10:33:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76709188.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定