7

Is there a standard way to compare two references for identity implementing essentially what is done bellow:

bool compareForIdentity(int& a,int& b){return &a==&b;}
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
George Kourtis
  • 2,381
  • 3
  • 18
  • 28
  • 12
    http://en.cppreference.com/w/cpp/memory/addressof – chris Sep 01 '14 at 20:54
  • I didn't even had realized that it may be possible to overload &. But any way. The std::addressof operator does any way what I did with &. It could e.g. be that the variable a is a register variable and b too. – George Kourtis Sep 01 '14 at 20:57
  • I would expect a more standard way of comparing references for identity. – George Kourtis Sep 01 '14 at 21:06
  • 1
    `register` hasn't meant what it seems to mean for a long time. – T.C. Sep 01 '14 at 21:27
  • You can take the address of a register variable in C++, even though you couldn't in K&R C more than 20 years ago. – Alan Stokes Sep 01 '14 at 21:30
  • 1
    Comparing references for identity is not a particularly common operation, and in most cases is trivial. What more were you expecting? – Alan Stokes Sep 01 '14 at 21:31
  • @AlanStokes Actually the following code doesn't compile because references to register variables aren't supported – George Kourtis Sep 01 '14 at 21:43
  • @AlanStokes #include register int a asm("%ebx");register int b asm("%r12"); int main(int argc, char **argv) { //int& aa=a;int& bb=b; int& aa=a; int& bb=b; printf("hello world\n"); return 0; } – George Kourtis Sep 01 '14 at 21:44
  • 4
    That's not standard C++. `register int a;`, which is, would work fine. – Alan Stokes Sep 01 '14 at 21:47
  • @AlanStokes If it works fine, then probably the compiler doesn't keep the variable in registers. – George Kourtis Sep 01 '14 at 22:03
  • 1
    Are you actually asking for a *standard* way to compare *non-standard* things? – T.C. Sep 01 '14 at 22:22
  • Indeed, George, a variable whose address has been taken cannot be in a register. That even plays a role when deciding whether an uninitialized and hence invalid address value can cause a trap (it can in a register). – Peter - Reinstate Monica Sep 01 '14 at 22:37
  • @PeterSchneider that thing about address and trap representations is only in C. In C++ you can take the address of a register variable. – M.M Sep 01 '14 at 22:44
  • @MattMcNabb: given `register int a;`, if you take the address of `a` then the compiler will ensure the value's stored in actual memory (ignoring the hint to keep it in a register) for *at least* as long as the address might be used to access the `int` value. Similar to taking the address of "inline" functions (whether explicitly coded as `inline` or implicitly inline due to definition within a class etc.). – Tony Delroy Sep 02 '14 at 02:58
  • @TonyD I mean, in C++ you can take the address of a variable declared with the `register` storage class specifier; and in C you cannot. – M.M Sep 02 '14 at 05:18
  • So finally we should be able to compare if two references are identical independently from the fact that these have an address representable as a 32bit or 64bit quantity of whatever. – George Kourtis Sep 02 '14 at 07:39
  • @TonyD Right; and the compiler may keep a variable in a register, of course, if its address is never taken; independently of any explicit `register` declaration. Taking its address (and, perhaps, using that address in a way which cannot be optimized away, although I'm not sure that that is a requirement) just ensures that it is NOT in a register, which can be important for uninitialized variables. – Peter - Reinstate Monica Sep 02 '14 at 08:13
  • @GeorgeKourtis: if you're writing for a class that you know hasn't overridden `operator&`, why would you want a `compareForIdentity(&a, &b)` function when `&a == &b` does the same thing and is - once you're used to it - even clearer? `std::addressof` if similar but makes it clear you want a general solution. What you're asking seems to boil down to "I don't like the notation to do this at the bare-bones level - why don't we have a nicely named convenience function?" but in my opinion that just raises more questions about what's meant by "identity". Comparing addresses is unambiguous. – Tony Delroy Sep 02 '14 at 09:01
  • As has been shown, it may be that & is overloaded, in that case &a==&b isn't the correct solution ( or may be -- semantics ). Suppose to be treating a bit field and use a reference to it that semantically has full sense, then the compiler could know if two references are the same but the operator addressof or "&" doesn't exists for that case. So the identity of references is something that doesn't depend on the existence of an address. We may also compare two different kind of objects that belong to different but related classes. In that case &a may be == &b but the objects may be different . – George Kourtis Sep 02 '14 at 13:28
  • @AlanStokes Re "Comparing references for identity is not a particularly common operation": Errr... *every* assignment operator under the sun? – Peter - Reinstate Monica Jun 18 '21 at 03:44

1 Answers1

7

If you want to ensure that the references do not refer to the same object then yes, comparing the addresses as you have shown is indeed the standard way. The (built-in) address operator returns the address of the object referred to, not the address of the reference (which can conceptually be considered just another name without any object representation). This is the semantics usually needed to e.g. ensure a NOP for a copy to itself.

To ensure that indeed the built-in address operator is used (as opposed to any overloads) seems to be possible if a little tricky, cf. How can I reliably get an object's address when operator& is overloaded?.

Other uses may of course require different semantics, e.g. logical equality instead of physical.

Community
  • 1
  • 1
Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62
  • Identity does exist even when a variable has not an address ( e.g. a register variable ). – George Kourtis Apr 24 '21 at 16:10
  • @George Surely. But: (1) Terminology is important: variable vs. objects (2) There surely are *objects* in registers, but you'll find it is hard to create a reference to it. Or perhaps the other way around: You'll find it is hard to have an object in a register once you create a reference to it. (I'm not saying that it is a language rule -- the language actually does not have rules concerning registers (e.g. no `register` storage class). So we are talking implementation details here. These details make it *very* unlikely that a compiler keeps objects to which references exist in a register.) – Peter - Reinstate Monica Apr 24 '21 at 19:04
  • Identity is a logical property that does not depend on the possibility to have an address as a referece. Moreover a refererence on the logical level could be something different from an address. Identity is clear what it is and does not depend on having the value in main memory. – George Kourtis Apr 26 '21 at 21:43
  • @GeorgeKourtis That is all correct. But the OP asks for references :-). The need to determine identity of an object *through two distinct expressions* also seems to logically require an alias of some kind. I *think* (maybe I'm missing something!) C++ knows of only two kinds of aliases, addresses and references. And you are right that references to register variables are theoretically possible, although they most likely do not exist in practice. (But yes, a compiler could do that, indeed.) – Peter - Reinstate Monica Apr 27 '21 at 05:07
  • @GeorgeKourtis Another thing is that as soon as an address is taken the object is necessarily in memory, and that is likely true for taking its address through a reference as well. – Peter - Reinstate Monica Apr 27 '21 at 05:08
  • A lot of time has passed, but the arguments regarding references do seem to me ( after so much time ) more incoherent than before. I mean e.g. void test(int &a){ int& b=a; someCodeInOrderToForget; std::cout << compareForIdentity(a,b); } . The result is that compareForIdentity prints true even if a is in a processor register that in any case has as such an address inside the processor registers memory space, even if that space is not mapped into the memory address space. To my opinion a method should exist in order to check for identity as it's a logical property – George Kourtis Jun 22 '21 at 22:46
  • @George I cannot understand what you are trying to say. In any case, **identity** is typically not a logical but a physical property (it is *the same object*). **Equality,** by contrast, is a logical property. In your case, a and b are identical because they are indeed *names for the same object.* – Peter - Reinstate Monica Jun 23 '21 at 07:43