В терминах шкалы величин:
Если epsilon
- малая доля величины величины (то есть относительной величины) в некотором определенном физическом смысле и A
и B
типа сопоставим в том же смысле, что я думаю, что следующее вполне корректно:
#include <limits>
#include <iomanip>
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <cassert>
template< typename A, typename B >
inline
bool close_enough(A const & a, B const & b,
typename std::common_type< A, B >::type const & epsilon)
{
using std::isless;
assert(isless(0, epsilon)); // epsilon is a part of the whole quantity
assert(isless(epsilon, 1));
using std::abs;
auto const delta = abs(a - b);
auto const x = abs(a);
auto const y = abs(b);
// comparable generally and |a - b| < eps * (|a| + |b|) / 2
return isless(epsilon * y, x) && isless(epsilon * x, y) && isless((delta + delta) / (x + y), epsilon);
}
int main()
{
std::cout << std::boolalpha << close_enough(0.9, 1.0, 0.1) << std::endl;
std::cout << std::boolalpha << close_enough(1.0, 1.1, 0.1) << std::endl;
std::cout << std::boolalpha << close_enough(1.1, 1.2, 0.01) << std::endl;
std::cout << std::boolalpha << close_enough(1.0001, 1.0002, 0.01) << std::endl;
std::cout << std::boolalpha << close_enough(1.0, 0.01, 0.1) << std::endl;
return EXIT_SUCCESS;
}
Цитата Вопросы и рекомендации по стилю и технике B ++ C ++ для Bjarne Stroustrup FAQ , причина, по которой размер отличен от нуля, - «Чтобы адреса двух разных объектов были разными». И размер может быть 1, потому что выравнивание здесь не имеет значения, поскольку на самом деле ничего не стоит смотреть.
В стандарте указано, что все наиболее производные объекты имеют sizeof ()> = 1:
Если это не бит-поле (class.bit), то наиболее производный объект должен иметь -zero и занимает один или несколько байтов памяти. Субъекты базового класса могут иметь нулевой размер. ISO / IEC FDIS 14882: 1998 (E) intro.object
blockquote>
Я думаю, что было бы полезно сослаться на ответ, объясняющий это тоже. Это о boost::compressed_pair
на Логан Капальдо .
Я думаю, что если размер пустого класса равен нулю, это означает, что он не существует. Чтобы он (класс) существовал, он должен иметь не менее 1 байт, так как этот байт является адресом памяти / ссылки.
Я думаю, что это так, потому что, поскольку 1 байт является наименьшим блоком памяти, который можно использовать в качестве заполнителя, и он не может дать нулевой размер, так как невозможно создать массив объектов.
и то, что вы сказали: «Это было немного удивительно для меня, поскольку я ожидал, что он будет иметь размер машинного слова (32 бита или 4 байта)». будет истинным для ссылочной переменной (слова macine) типа empty (), а не для самого класса (который является абстрактным типом данных),
Я думаю, что этот вопрос имеет только теоретический интерес, но на практике он не имеет значения.
Как уже указывалось другими, вывод из пустого класса не наносит никакого вреда, поскольку это не будет потребляет любую дополнительную память для части базового класса.
Кроме того, если класс пуст (что означает, что теоретически - не требуется какая-либо память для каждого экземпляра, т. е. статические члены данных или виртуальные функции-члены), то все его функции-члены могут быть одинаковыми (и должны) быть определены как статические. Поэтому нет необходимости когда-либо создавать экземпляр этого класса.
Нижняя строка: если вы обнаруживаете, что пишете пустой класс X, просто ставьте все функции-члены. Тогда вам не нужно создавать объекты X, и производные классы никак не будут затронуты.
Существует исключение: массивы длиной 0 строк
#include <iostream>
class CompletlyEmpty {
char NO_DATA[0];
};
int main(int argc, const char** argv) {
std::cout << sizeof(CompletlyEmpty) << '\n';
}
c
, &c[M] == &c[N]
для каждого M
и N
(clang ++ 4.1).
– Konstantin Nikitin
1 January 2013 в 17:28
Это из-за этого указателя, хотя указатель (целое) из 4 байтов, но он относится к одной ячейке памяти (одному модулю), которая равна 1 байт.
Это действительно деталь реализации. Когда-то давно я думал, что это может быть нулевой байт или тысяча байт, что он не имеет никакого отношения к спецификации языка. Но, посмотрев на стандарт (раздел 5.3.3), sizeof
определяется как всегда возвращающий один или более, независимо от того, что.
Размер самого производного класса должен быть больше чем нуль.
blockquote>Это требуется, помимо прочего, для обработки массивов объектов и указателей. Если вашим элементам было присвоено нулевое значение, то
&(array[0])
будет идентичным&(array[42])
, что вызовет всевозможные хаосы для ваших циклов обработки.Причина, по которой это может быть не так машинное слово состоит в том, что в нем нет элементов, которые фактически требуют, чтобы он был выровнен на границе слова (например, целое число). Например, если вы помещаете
char x; int y;
внутри класса, мой GCC синхронизирует его с восемью байтами (поскольку второй int должен быть выровнен в этой реализации).
Это может помочь u :-) http://bytes.com/topic/c/insights/660463-sizeof-empty-class-structure-1-a
Размер пустого класса или структуры равен 1
. Причина, по которой это происходит, сводится к правильной реализации стандарта, что говорит о том, что «ни один объект не должен иметь тот же адрес в памяти, как и любая другая переменная ".... Что является самым простым способом обеспечить это? Убедитесь, что все типы имеют ненулевой размер. Для этого компилятор добавляет фиктивный байт к структурам и классам, у которых нет элементов данных и нет виртуальных функций, поэтому они имеют размер 1, а не размер 0, и тогда у них гарантированно будет уникальный адрес памяти.
blockquote>
причина для класса без элементов данных, но имеющих размер 1 байт, состоит в том, что этот * сильный текст * должен храниться в памяти, чтобы ссылка или указатель могли указывать на объект этого класса
#include<iostream>
using namespace std;
class Empty { };
int main()
{
Empty* e1 = new Empty;
Empty* e2 = new Empty;
if (e1 == e2)
cout << "Alas same address of two objects" << endl;
else
cout << "Okay it's Fine to have different addresses" << endl;
return 0;
}
Выход: Хорошо, что у вас разные адреса
Возвращаемый размер 1 гарантирует, что два объекта не будут иметь один и тот же адрес.
Выделение 1 байта для пустого класса зависит от компилятора. Компиляторы должны убедиться, что объекты находятся в разных ячейках памяти, и им необходимо выделить ненулевой размер памяти для объекта. Слушайте заметки по этой теме здесь: http://listenvoice.com/listenVoiceNote.aspx?id=27
Хотя компиляторы выделяют ненулевой размер в пустой класс, они также делать оптимизации, когда новые классы производятся из пустых классов. Слушайте о оптимизации базовой базы в вопросах интервью с программированием на С ++.
Не забудьте гарантировать, что два разных объекта будут иметь разные адреса. Различные объекты должны иметь разные адреса, поэтому размер пустого класса всегда 1 байт.
new
; когда пространство выделено, другое распределение должно иметь другой адрес. И так далее. В пустом классе необязательно есть указатель; могут быть указатели на переменные (или ссылки или локальные / стековые распределения), но они не являются нулевым размером, и они не обязательно являются размером указателя. – Jonathan Leffler 28 February 2014 в 22:35