1. Это пример бритвы Оккама, принятый драконов, которые на самом деле писать компилятор: Не дают больше гарантий, чем необходимо, чтобы решить эту проблему, потому что в противном случае ваша рабочая нагрузка будет удвоена без компенсации. Сложные классы, адаптированные к фантастическому оборудованию или к историческому оборудованию, были частью проблемы. (Намекая на BaummitAugen и M.M)
2. (смежный = разделяя общую границу, рядом или вместе в последовательности)
Во-первых, это не то, что объекты типа Т всегда или никогда не занимают непрерывного хранения. В одном бинарнике могут быть разные макеты памяти для одного и того же типа.
[class.derived] §10 (8): Базовый класс подобъектов может иметь компоновку, отличную от ...
Это было бы достаточно, чтобы откинуться назад и быть уверен, что то, что происходит на наших компьютерах не противоречит стандарту. Но давайте исправим вопрос. Лучше задать вопрос:
Является ли стандартное разрешение массивами объектов, которые не занимают непрерывное хранение отдельно, в то же время каждый два последовательных подобъекта имеют общую границу?
Если это так, это сильно повлияет на то, как char * арифметика относится к арифметике T *.
В зависимости от того, понимаете ли вы стандартную цитату OP, означающую, что только субообъекты имеют общую границу или что также в каждом подобъекте байты имеют общую границу, вы можете прийти к разным выводам.
Предполагая, что первый, вы обнаружите, что «смежно выделено» или «хранятся смежно» может просто означать & а [п] == & а [0] + п (§23.3.2.1), которая является утверждение о subobject, что не означает, что массив находится в пределах одной последовательности смежных байтов.
Если предположить сильную версию, вы можете прийти к «элементу смещение == SizeOf (T)» вывод перенесенный в T* versus char* pointer arithmetic Это также означает, что один может заставить иначе возможно несмежные объекты в пределах макета объявив их T t [1]; вместо T t;
Теперь, как решить эту проблему?Существует принципиально неоднозначное определение оператора sizeof() в стандарте, который, по-видимому, является реликтоном того времени, когда, по крайней мере, на архитектуру, грубо сравните макет, что уже не так. (How does placement new know which layout to create?)
В применении к классу, результат [из SizeOf()] является количеством байт в объекте этого класса, включая любые дополнения, необходимые для размещения объектов данного типа в массиве. [expr.sizeof] §5.3.3 (2)
Но подождите, количество требуемого заполнения зависит от компоновки, а один тип может иметь более одного макета. Таким образом, мы обязаны добавить зерно соли и взять минимум на все возможные макеты или сделать что-то одинаково произвольное.
Наконец, определение массива выиграет от значения в терминах char * арифметики, если это предназначение. В противном случае ответ на вопрос 1 применяется соответственно.
Несколько замечаний, связанных с компанией удаляемых ответы и комментарии: Как обсуждается в Can technically objects occupy non-contiguous bytes of storage?, несмежные объекты на самом деле существуют. Кроме того, memseting подобъекта наивности может привести к аннулированию несвязанных подобъектов содержащего объекта, даже для абсолютно непрерывных, тривиального Copyable объектов:
#include <iostream>
#include <cstring>
struct A {
private: int a;
public: short i;
};
struct B : A {
short i;
};
int main()
{
static_assert(std::is_trivial<A>::value , "A not trivial.");
static_assert(not std::is_standard_layout<A>::value , "sl.");
static_assert(std::is_trivial<B>::value , "B not trivial.");
B object;
object.i=1;
std::cout<< object.B::i;
std::memset((void*)&(A&)object ,0,sizeof(A));
std::cout<<object.B::i;
}
// outputs 10 with g++/clang++, c++11, Debian 8, amd64
Таким образом, можно предположить, что MemSet в вопросе посте может нуль а [1]. i, так что программа будет выводить 0 вместо 3.
Существует несколько случаев, когда можно было бы использовать memset-подобные функции с объектами C++. (Обычно деструкторы подобъектов будут ошибочно выполняться, если вы это сделаете.) Но иногда хочется счистить содержимое «почти-POD'-класса» в своем деструкторе, и это может быть исключение.
Что значит объект не занимает смежное пространство? Вы говорите о дополнении, которое может находиться между переменными-членами? – NathanOliver
Математика говорит, что запрос «разреженных массивов» в Google может помочь вам ??? , извините, мой английский слишком плохой, чтобы помочь глубже. –
Для вашего первого вопроса: Потому что никто не хочет проектировать C++ вокруг C-материала, такого как 'memset'. C-структурам необходимо работать с 'memset' для совместимости, остальное на самом деле не имеет значения. –