我在这里收到结构副本吗?

时间:2009-02-26 19:34:33

标签: c++ reference overwrite

这是假代码示例

vector<Fred> gFred;
{
    // init gFred

    Fred &fred = gFred[0];

    size_t z = 0;
    do
    {
        fred = gFred[z];

        // do odd processing with fred

        z++;
    }
    while (fred.lastElementInSet == 0);
}

引起我注意的是gFred [0]被覆盖的事实。 这使我认为,而不是将init作为对新元素的引用,

fred = gFred[z];

实际发生的是gFred [1]覆盖了gFred [0]。

我在想这里做的正确的事情,就是把自己带到头几次,把它变成一个指针实现并继续我的生活。

我是否正确诊断出这一点?还是我需要更多的教育?

5 个答案:

答案 0 :(得分:6)

是的,你在那里得到一份结构副本。引用不能反弹,即它们在初始化后保持不变。

您的解决方案也是合适的。尽管如此,邓诺还是打了个招呼。

答案 1 :(得分:3)

查看引用的一种方法是将它们视为隐式取消引用的指针。简单地说,它们是指针,但您可以使用常规变量访问语法来使用它们

Fred &fred = gFred[0];

这将创建对向量gFred的第一个元素的引用。 (顺便说一句,你有什么内容吗?)编译器会做这样的事情:

Fred *pFred = &gFred[0];

现在,当你这样做时:

fred = gFred[z];

编译器实际上会做这样的事情:

*pFred = gFred[z];

翻译为:

gFred[0] = gFred[z];

如果你的N中有N个要素,那么你vector次这样做了。

如果您尝试初始化vector的所有元素,请尝试使用此构造函数:

vector(size_type n, const T& t)      

其中,

n = size of vector
t = gFred[0]

答案 2 :(得分:1)

使用您发布的代码(假设Fred类型是POD),gFred [0]正在被覆盖并最终将包含gFred [z]中最后一个z的副本。

您可以切换到使用指针实现,或者您可以更仔细地调整参考范围:

{    
    size_t z = 0;
    do
    {
        Fred &fred = gFred[z];
        // do odd processing with fred
        z++;
    }
    while (fred.lastElementInSet == 0);
}

答案 3 :(得分:0)

在您提供的代码中,fred始终引用gFred[0]。如果您希望fred引用随循环的每次迭代而更改,请删除行Fred &fred=gFred[0];。然后将fred = gFred[z];替换为Fred &fred = gFred[z]。这样,每次循环执行时都会重新初始化fred引用。

答案 4 :(得分:0)

编译机制由dirkgently的答案解释,而基本的解释是MSN的(“引用不能反弹”)。

也许以这种方式阅读会更容易:

如果

ptr = &xxx;

表示ptr的内容是xxx的地址,然后是

&fred = gFred[0];

表示fred地址设置为指向gFred[0]。 IOW,fred现在是gFred[0]的别名。这就是为什么要fred = xxx覆盖gFred[0]