If I have a vector of shared_ptr whereas one of the shared_ptrs are pointing to object Foo, and Foo is deleted, does the vector erase the element with a shared_ptr to Foo? From what I understood this is not the case, and hence not a solution to my problem... Although it is very likely I have misunderstood the concept of shared_ptr. To me it seems that shared_ptr can be dangling aswell since the vector still has an element where the shared_ptr to A used to be located.
With shared_ptr<>, the object is only deleted when the last shared_ptr is itself destroyed. So if you remove a Goblin from the list of objects in the world, the Goblin is not yet deleted unless the trap is also destroyed. This is probably not what you want.
The other approach is to have a mixture of shared_ptr<> and weak_ptr<>. Weak pointer indicates knowledge of the existence of a given Goblin, but does not actually keep it alive. When you want to use a weak_ptr<>, you must first "lock" it, creating a shared_ptr<> while you do your work. You can also test if the weak_ptr<> still points to something. Provided that this shared_ptr<> is transient, this would allow for your Goblin / Trap scenario.
I have trouble understanding how a trap could smash the goblin unless the trap has a pointer to the goblin...
Presuming that the Trap is an area affect, I would design this so that the Trap creates some kind of notification callback inside the physics / collision code. When a Goblin, or any object, enters the area that the Trap has defined, the engine calls back into the trap, passing a (transient) pointer/reference to the game object. The trap can then apply damage to that object, and optionally remove itself from the callback code (if it is a one-use trap).
... or how the quality of an item would be if not the workbench has a pointer to the crafter.
Set the quality of an object only when it is actually created. You can have a collection of item prototypes on the workbench - it is only when a crafter uses the workbench that you create a fully item object with various statistics.
Inevitably there will be much pointers to Units for all I know.
The two approaches I mentioned above try to minimise this inter-object dependencies. Try to structure the game so that objects only know about each other briefly - just when they are in the middle of some interaction. One way to break the dependency is by using some kind of "world" object that provides an interface for querying the game world and game objects around each object.
Now, this doesn't always work. For instance, a homing fireball spell must have a persistent way to "remember" the actor it is chasing. One way to handle that is using a weak_ptr<> like above. Another is for the spell to store an object identifier, and for the spell to periodically query the world to determine the status of its victim. Finally you might have a callback system where the spell can register to "listen" to changes in the victim, such as them moving or dying.