2

the operator "===" should compare class references to determine if both sides are referring same object:

var objectA : NSNumber = 1
var objectB : NSNumber = 1

print(objectA === objectB)
// return true, 

so my question is NSNumber wrapped the object into the same object, how is the back-end logic of doing so.

jtbandes
  • 115,675
  • 35
  • 233
  • 266
JH_EARTH
  • 53
  • 1
  • 7
  • 1
    https://mikeash.com/pyblog/friday-qa-2012-07-27-lets-build-tagged-pointers.html – jtbandes Nov 25 '16 at 02:10
  • @jtbandes: That is very cool. I wish the JDK did something like that. Much better than the cache of a few internalized instances for frequently used values. – Thilo Nov 25 '16 at 02:11
  • 2
    Both NSNumber and NSString get Special Treatment (tm, pat.pend., all rights reserved). – matt Nov 25 '16 at 02:15
  • @Thilo Well the JVM does do internment for Strings, at least – Alexander Nov 25 '16 at 02:17
  • 1
    This is basically a dupe of http://stackoverflow.com/questions/4270121/why-nsnumber-points-to-the-same-address-when-value-are-equals but that addresses this issue from an Objective-C point of view. – rmaddy Nov 25 '16 at 02:19
  • @Thilo I don't have any experience with the JDK, so I can't really comment, but it seems like a very similar optimization. Not **all** NSNumbers can be represented this way, for instance I just tried `0xFFFFFFFFFFFFFFF` and it gives me a new object. – jtbandes Nov 25 '16 at 02:22
  • 1
    @rmaddy Yes, looks like it, although the answers on that question are woefully out of date :( – jtbandes Nov 25 '16 at 02:25
  • Also here: [iOS - Why Does It Work When I Compare Two NSNumbers With “==”?](http://stackoverflow.com/questions/34104085/ios-why-does-it-work-when-i-compare-two-nsnumbers-with) – Martin R Nov 25 '16 at 03:44
  • @matt **1)** So `String` doesn't get this special treatment because it's value type but NSString does get it because it's reference type? **2)** I tried two numbers with the same literal value and it returned true, however when I tried to NSStrings with the same literal value it returned false, so I'm confused when you say they get special treatment. Do you mean the special treatment of NSString and NSNumber is different from one another? – mfaani Nov 25 '16 at 14:09

1 Answers1

2

NSNumber is one of a small handful of classes which can sometimes be represented as tagged pointers (at least on Apple platforms; I don't think this applies to the open-source version of (Core)Foundation).

Basically, this means that rather than a pointer to an actual instance of a class located elsewhere in memory, the NSNumber stores its value (in this case 1) directly inside the pointer. You can see this for yourself:

import Foundation

let x: NSNumber = 1
let y: NSNumber = 2

// Tagged pointers: the number is stored inside the pointer representation.
print(Unmanaged.passUnretained(x).toOpaque())  // 0x0000000000000137
print(Unmanaged.passUnretained(y).toOpaque())  // 0x0000000000000237

class C {}
let c = C()

// Not a tagged pointer; just a regular pointer to allocated memory.
print(Unmanaged.passUnretained(c).toOpaque())  // 0x00007fb32276daa0

The same optimizations can apply to NSString and other types too. For more details, read Mike Ash's excellent in-depth blog posts:

Don't rely on this, however. It's just an implementation detail, and not all NSNumbers may be represented this way. The correct way to compare them for equality is ==.

jtbandes
  • 115,675
  • 35
  • 233
  • 266