Traditionally, Objective-C didn't provide any memory management facilities. In early versions, the root Object class implemented a +new method that called malloc() to create a new object. When you had finished with the object, you sent it a -free message. OpenStep added reference counting. Every object that inherits from NSObject responds to a -retain and a -release message. When you want to retain a pointer to an object, you send it a -retain message. When you've finished with it, you send it a -release message.
This design has one slight problem. Often you don't want to keep a pointer to an object, but you don't want it to be freed quite yet, either. A typical example is when returning an object. The caller may want to keep a pointer to the object, but you don't.
The solution to this problem was the NSAutoreleasePool class. In addition to -retain and -release, NSObject also responds to an -autorelease message. When you send one of these, it registers itself with the current autorelease pool. When this pool object is destroyed, it sends a -release message to every object that received an -autorelease message earlier. In OpenStep applications, an NSAutoreleasePool instance is created at the start of every run loop and destroyed at the end. You can also create your own instances to free autoreleased objects sooner.
This mechanism eliminates a lot of the copying that C++ needs. It's also worth noting here that, in Objective-C, mutability is an attribute of the object, not of the reference. In C++, you have const pointers and non-const pointers. You're not allowed to call non-const methods on a const object. This doesn't guarantee that the object won't be changed—simply that you won't change it.
In Objective-C, a common pattern defines an immutable class and then a mutable subclass. NSString is a typical example; it has a mutable subclass, NSMutableString. If you receive an NSString and you want to keep it, you can send it a -retain message and keep the pointer without a copy operation. Alternatively, you could send NSString a +stringWithString: message. This then checks whether the argument is mutable, and, if it isn't, returns the original pointer.
Objective-C 2.0 from Apple and the GNU runtime both support conservative garbage collectors, which allow you to avoid the need for -retain and -release messages. This addition to the language isn't always well-supported by existing frameworks, however, and should be used with care.