2

Given the following code:

struct Tag {};
struct X {
//    Tag t; // if not commented it shouldn't be pointer-interconvertible
    int k;
};

int fn(const X& x, int& p) {
    int i = x.k;
    p = 2;
    return i + x.k;
}

The generated code is:

fn(X const&, int&):
        mov     eax, DWORD PTR [rdi]
        mov     DWORD PTR [rsi], 2
        add     eax, DWORD PTR [rdi]
        ret

Here the compiler assumes aliasing.

If member t is not present, the types X and int are pointer-interconvertible. As so, the compiler must generate code as if the references could alias.

But if member t is present, they should no longer be pointer-interconvertible and code for the non-aliased case should be generated. But in both cases the code is identical except the relative address of member k.

The assembler:

fn(X const&, int&):
        mov     eax, DWORD PTR [rdi+4]
        mov     DWORD PTR [rsi], 2
        add     eax, DWORD PTR [rdi+4]
        ret

As an counter-example

template<typename T>
struct X {int k; };

int fn(X<struct A>& x, X<struct B>& p) {
    int i = x.k;
    p.k = 2;
    return i + x.k;
}

in the above version the generated code assumes no aliasing, but the types are pointer-interconvertible.

fn(X<A>&, X<B>&):
        mov     eax, DWORD PTR [rdi]
        mov     DWORD PTR [rsi], 2
        add     eax, eax
        ret

Can anyone explain this?

4

2 回答 2

4

这里

int fn(const X& x, int& p) {
    int i = x.k;
    p = 2;
    return i + x.k;
}

编译器必须假定它p可能是对x.k. p和都是x.k类型的左值int。因此,它们可能会相互混淆。指针是否X可与 a 相互转换int并不会改变p可能是对 . 的引用的事实x.k

这里

int fn(X<struct A>& x, X<struct B>& p) {
    int i = x.k;
    p.k = 2;
    return i + x.k;
}

另一方面,X<struct A>X<struct B>完全不相关的类型。x并且p不能是对同一对象的引用。因此,x.kandp.k不能表示相同的子对象。X<struct A>以及X<struct B>两者都可以与 an 指针相互转换的事实int再次无关紧要......

于 2020-01-28T20:40:10.563 回答
3

这里

int fn(const X& x, int& p) {
    int i = x.k;
    p = 2;
    return i + x.k;
}

X::kintp是对 的引用intp可以作为参考x.k

另一方面,这里:

int fn(X<struct A>& x, X<struct B>& p) {
    int i = x.k;
    p.k = 2;
    return i + x.k;
}

X<struct A>并且X<struct B>是不同的类型。没有办法让它xp/或部分引用同一个对象。

但是如果 k 是私有的并且 X 有 operator int() const 返回 k 怎么办?

然后什么都没有改变。马虎地说,你需要一个参考/指针来获得潜在的混叠。例如

struct G {};
struct H { G* g; }

void foo(G* a,H b);

这里b.ganda可以指向相同的G(注意无论b是通过值、引用还是指针传递都是这种情况)。在你的例子中......

template<typename T>
struct X {int k; };
int fn(X<struct A>& x, X<struct B>& p)

.. 唯一的参考是xp。它们指的是不同类型的对象,也就是不同的对象。

于 2020-01-28T20:41:52.270 回答