const引用的地址是否可能与所引用对象的地址不同?

6

我遇到了与以下代码等效的问题:

const auto &const_reference = some_object;
assert(&const_reference == &some_object);

当我使用g++ -O3标志编译它时,它无法通过断言。当没有优化编译时,断言被通过。
据我所知,即使我的项目中存在未定义行为,这种情况也不应该发生。
在何种情况下,引用的此类行为是可以预期的?
编辑:实际代码链接:https://github.com/Gray0Ed/ggp_thesis/blob/67606021020546b315ad63b7fd5c2203f3e0086f/rule_engine/aligner.cpp#L177 - 项目有点混乱,并不真正准备好公开展示,但如果你好奇,请随意查看。
编辑2:如RustyX指出,原始代码与我上面给出的“等效”代码不同,请查看他的答案以了解详细信息。

5
由于“const_reference”和“some_object”引用相同对象,因此等式始终应该成立。这很可能是未定义行为的症状,但无法猜测原因。(唯一的其他可能性是编译器错误,但这不太可能。)请先发布一些实际代码,而不是“等效”的代码。 - molbdnilo
什么版本的gcc?这可能是编译器的一个bug,我的gcc认为即使使用-O3也没问题。 - Elijan9
3
你是否重载了 operator & 运算符? - Jarod42
如果你在其他地方有未定义的行为,一切皆有可能。 - Jarod42
1
该对象是否继承自另一个类? 您是否执行强制类型转换,因为这可能会导致对象的不同地址... - Jonathan
另一种可能性是:some_object 突然引用了另一个对象,因为它在另一个作用域中被重新定义了。例如:int i; int& ri = i; { int i; assert (&i != &ri); } - MSalters
1个回答

5
这段代码永远有效:
    const auto &const_reference = some_object;
    assert(&const_reference == &some_object);

实际上无法正常工作的代码实际上是这样的:
    const auto &oc = ai->var_infos[var_id].occurences[0];
    assert(&oc == &ai->var_infos[var_id].occurences[0]);

由于您过载了operator[],所以它无法正常工作:

请查看MyArrays.hpp:

T operator[](size_t i) const {
    assert(size >= 0);
    assert(i < size && i >= 0);
    return items[i];
}

每次调用它时,都会返回一个副本
应该改为:
const T& operator[](size_t i) const {
    assert(size >= 0);
    assert(i < size && i >= 0);
    return items[i];
}

1
特别是第一个 [] 会进行复制,因为 ai 是指向 const 的指针,然后第二个 [] 在非 const 临时副本上调用,返回到该副本的引用,导致一团糟。 - T.C.
哇,非常感谢你RustyX,当然你是对的。我给了你部分错误的信息,你仍然成功解决了问题。我真是太不好意思了。 - Gray0Ed
@RustyX,你有没有想法为什么这个表达式&ai->var_infos[var_id].occurences[0]没有产生“error: lvalue required as unary ‘&’ operand”错误? - krdln

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接