Почему адреса двух разных объектов должны быть разными?

Я читал об этом, что размер объекта должен быть не менее 1 байта (C++: каков размер объекта пустого класса?) и что плохого в том, что два пустых объекта имеют один и тот же адрес ? В конце концов, у нас может быть два указателя на один и тот же объект.

The googling говорит мне, что есть что-то о правиле идентификации объекта fundemantal, но я не могу найти более подробную информацию об этом.

Так... $ТЕМА.

5 ответов


наличие двух объектов по одному адресу означало бы, что не было бы никакого способа различать эти два объекта при ссылке на них указателями. Например, в следующем коде:

EmptyClass o1;
EmptyClass o2;

EmptyClass * po = &o;
po->foo();

если метод foo вызывается на o1 или o2?

можно утверждать, что, поскольку эти объекты не имеют данных и виртуальных методов (иначе они имели бы ненулевой размер), не имеет значения, на каком экземпляре вызывается метод. Однако, это становится более важным, когда мы хотим проверить, если два объекта равны (т. е. если они одинаковы):

template < typename T >
bool isSame( T const & t1, T const & t2 )
{
    return &t1 == &t2;
}

EmptyClass o1; // one object and...
EmptyClass o2; // ...a distinct object...

assert( ! isSame( o1, o2 ) ); // ...should not be one and same object!

для более конкретного примера, предположим, что я хочу связать некоторые объекты (я мог бы сказать лиц) с некоторыми значениями, скажем, в ассоциативный контейнер:

Person you;
Person me;

// You and I are two different persons
// (unless I have some dissociative identity disorder!)
// Person is a class with entity semantics (there is only one 'me', I can't make
// a copy of myself like I would do with integers or strings)

std::map< Person *, std::string > personToName;

personToName[&you] = "Andrew_Lvov";
personToName[&me]  = "Luc Touraille";
// Oh, bother! The program confused us to be the same person, so now you and I
// have the same name!

Итак, да, все сводится к объектной идентичности: если бы объектам было разрешено быть пустыми, они могли бы быть лишены своей идентичности, что просто не допускается языком (к счастью.)


каждый объект должен занимать отдельное хранилище, иначе вы не можете освободить один объект без освобождения других, которые разделяют хранилище с ним.

Предположим, у вас есть два разных объекта на один адрес:

Type* object1 = new Type(); //first object
Type* object2 = new Type(); //second object

и они оказались по тем же адресам, тогда вы

delete object1;

что будет deleteD, если они оба имеют один и тот же адрес?


C++ есть (среди прочего) правило, которое говорит, что указатели на объекты считаются равными, если и только если указатели ссылаются на один и тот же объект. Согласно сценарию, который вы предлагаете, это больше не будет правдой.

есть также довольно много кода, который просто предполагает sizeof также даст строго положительный результат. Jut например, довольно много кода использует такие вещи, как:

#define elements(array) ((sizeof(array)/sizeof(array[0]))

для объектов с размером ноль, это приведет к 0/0, который математически не определено.

вместо того, чтобы вносить изменения везде, чтобы поддерживать один угловой случай, было намного проще просто устранить угловой случай, чтобы он соответствовал существующим правилам.


когда у вас есть два указателя на один и тот же объект, можно использовать для управления объектом. Результат = вы можете получить доступ к объекту.

однако, если у вас есть два объекта по одному адресу, как бы вы различали их в памяти? Если бы у вас был указатель на этот адрес, как бы вы узнали, на какой объект указывал ваш указатель?

следовательно, для каждого объекта нужны разные адреса, даже если они пусты.


попробуем провести аналогию.

Если у вас есть две машины, и вы пытаетесь, чтобы они занимали одно и то же физическое пространство, вы будете иметь аварии.

Если у вас есть два объекта, и вы пытаетесь, чтобы они занимали одно и то же пространство памяти, вы также будете иметь сбой.