Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> перегрузка new и delete к классах, надо разобраться с механизмом 
V
    Опции темы
null56
Дата 24.12.2008, 23:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 2
Всего: 12



Тема поднималась на форуме, но кусками, мне бы хотелось по подробнее разобраться с перегрузкой операторов new и delete и понять их области действия

Прежде всего хочу понять, что же означает 
Код

new
:: new
:: operator  new

и в каком контексте

В качестве примера, я набросал небольшой код, по которому и хочу разобраться...

Функция main стандартная
Код

Test * p_pointer = new Test;
delete p_pointer;


Вот первый вариант кода, который, должен быть правильным (если не так, поправьте обязательно)
Код

class Test
{
        public:
                Test() {printf("Constructor\n");}
                ~Test() {printf("Destructor\n");}
                //-
                void * operator new(size_t size) throw()
                {
                        printf("operator new\n");
                        void * p_var = 0;
                        p_var = :: operator new (size);
                        return p_var;
                }
                //-
                void operator delete (void * pObj)
                {
                        printf("operator delete\n");
                        if (pObj != 0)
                        {
                                printf("Object not empty");
                                :: operator delete (pObj);
                        }
                }
};


Вывод в консоль будет следующим
Код

operator new
Constructor
Destructor
operator delete
Object not empty


Что же получается???
NEW: глобальный (???) оператор new вызывает мой перегруженный метод new, в котором уже вызовом :: operator new(size), я создаю объект?
DELETE: глобальный () вызывает ДЕСТРУКТОР(???), который потом вызовит мой перегруженный метод, в котором я удалю объект???
Очень странно....

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

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

Заранее благодарен за помощь...
PM MAIL   Вверх
UnrealMan
Дата 25.12.2008, 00:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 27
Всего: 32



Подробная информация по интересующим тебя вопросам есть в стандарте C++ (ищи pdf файл, а в нём пп. 5.3.4 New, 5.3.5 Delete).

Это сообщение отредактировал(а) UnrealMan - 25.12.2008, 00:25
PM MAIL   Вверх
null56
Дата 25.12.2008, 16:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 2
Всего: 12



Почитал я спецификацию, посмотел файлик new, посмотрел еще вот эту тему...
http://forum.vingrad.ru/forum/topic-241511...y1737737/0.html

Не все до конца ясно...

1) new и operator new - это разные вообще вызовы? 
operator new - выделяет память нужного размера, так как его аргументы могут быть лишь 
Код

void* operator new(std::size_t) throw (std::bad_alloc);
void* operator new[](std::size_t) throw (std::bad_alloc);
//-
void* operator new(std::size_t, const std::nothrow_t&) throw();
void* operator new[](std::size_t, const std::nothrow_t&) throw();
// Default placement versions of operator new.
inline void* operator new(std::size_t, void* __p) throw() { return __p; }
inline void* operator new[](std::size_t, void* __p) throw() { return __p; }


2) Двоеточие перед new или operator new означает вызов глобальный (НЕ ПЕРЕОПРЕДЕЛННЫХ МНОЙ) методов языка
3) Функция new вызывает operator new с нужными параметрами
3) Вызывая в основной функции new к моим объектам (так как без двоеточия), вызывается глобальная функция new, которая вызывает метод operator new, но вызывает его из мной переопределенного operator new, где я уже ручками должен вызвать глобальный метод operator new(размер объекта), так получается? и вот тогда создается мой объект, поэтому и вызвается конструктор, после чего возращается управление глобальному методу new, который уже инициализирует конструктор значением

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

Правильно я это понимаю, опишите пожалуйста, что не так я написал? Мне кажется, что в конструкторе я не совсем понимаю правильно....
Ранее вы писали

Цитата

Собственно, new-выражение вызывает функцию operator new и передаёт ей свои аргументы. Первый аргумент - это всегда размер памяти, остальные аргументы (в случае их наличия) передаются в том же порядке, в котором они указаны в new-выражении. Т.е., например,

Выделить всёкод C++
1:
    
new(1, 2, 3, 4) T

вернёт результат

Выделить всёкод C++
1:
    
operator new(sizeof(T), 1, 2, 3, 4)

преобразованный к T *. Инициализация может быть, а может и не быть - это зависит от нескольких факторов.


разве это так? 

Я пытаюсь сделать в своем методе
Код

void * SocketHandler :: operator new(unsigned int size) throw()
{
    qDebug("My new");
    qDebug("%d", id);
    int &index = 10;
    void * pp = :: operator new (size, &index);
    return  pp;
}


Но у меня вылетает ошибка сегментации

Или так делать нельзя???

Добавлено @ 16:27
и судя по всему метод new "мой объект" генерит не глобальный, как я выражался, а свой, который буддет применяться к моему объекту



Это сообщение отредактировал(а) null56 - 25.12.2008, 16:39
PM MAIL   Вверх
UnrealMan
Дата 25.12.2008, 17:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 27
Всего: 32



Цитата(null56 @  25.12.2008,  16:24 Найти цитируемый пост)
1) new и operator new - это разные вообще вызовы?

В первом случае new - это часть new-expression, а operator new - это allocation function.

Цитата(null56 @  25.12.2008,  16:24 Найти цитируемый пост)
так как его аргументы могут быть лишь 

Параметры могут быть и другими, если определять функции operator new самому. У предопределённых функций operator new параметры такие, как ты привёл.

Цитата(null56 @  25.12.2008,  16:24 Найти цитируемый пост)
2) Двоеточие перед new или operator new означает вызов глобальный (НЕ ПЕРЕОПРЕДЕЛННЫХ МНОЙ) методов языка

При наличии двойного двоеточия в new-expression или непосредственно перед operator new вызывается глобальная функция operator new.

Цитата(null56 @  25.12.2008,  16:24 Найти цитируемый пост)
Вызывая в основной функции new к моим объектам (так как без двоеточия), вызывается глобальная функция new, которая вызывает метод operator new, но вызывает его из мной переопределенного operator new, где я уже ручками должен вызвать глобальный метод operator new(размер объекта), так получается?

Нет. При использовании new-expression без :: компилятор сперва ищет operator new в твоём классе. Если поиск этой функции в твоём классе завершился бы неудачей, поиск продолжился бы в global scope. Вот оно правило:

Цитата(5.3.4 New абзац 9)
If the new-expression begins with a unary :: operator, the allocation function’s name is looked up in the global scope. Otherwise, if the allocated type is a class type T or array thereof, the allocation function’s name is looked up in the scope of T. If this lookup fails to find the name, or if the allocated type is not a class type, the allocation function’s name is looked up in the global scope.

С operator delete аналогично.

Цитата(null56 @  25.12.2008,  16:24 Найти цитируемый пост)
Я пытаюсь сделать в своем методе
Код
void * SocketHandler :: operator new(unsigned int size) throw()
{
    qDebug("My new");
    qDebug("%d", id);
    int &index = 10;
    void * pp = :: operator new (size, &index);
    return  pp;
}

1) int &index = 10 - так делать нельзя.
2) :: operator new (size, &index) не будет выделять память. Функция operator new, которая здесь будет вызвана, просто возвращает переданный в неё указатель, чтобы можно было записывать так:

Код
// выделяем неинициализированную память под 5 объектов типа std::string
void *p = ::operator new(5 * sizeof(std::string));

// конструируем один объект std::string в ранее выделенной памяти
// (неиспользованную память можно будет задействовать позже по мере необходимости)
std::string *s = static_cast<std::string *>(::new(p) std::string("some string"));

В последней строчке new-expression сначала вызывает ::operator new(sizeof(std::string), p) - при этом ничего полезного не делается - после чего в соответствии с правилом

Цитата(5.3.4 New абзац 15)
A new-expression that creates an object of type T initializes that object as follows:
— If the new-initializer is omitted:
    — If T is a (possibly cv-qualified) non-POD class type (or array thereof), the object is default-initialized
(8.5). If T is a const-qualified type, the underlying class type shall have a user-declared default constructor.
    — Otherwise, the object created has indeterminate value. If T is a const-qualified type, or a (possibly cv-qualified) POD class type (or array thereof) containing (directly or indirectly) a member of const-qualified type, the program is ill-formed;
— If the new-initializer is of the form (), the item is value-initialized (8.5);
— If the new-initializer is of the form (expression-list) and T is a class type, the appropriate constructor is called, using expression-list as the arguments (8.5);
— If the new-initializer is of the form (expression-list) and T is an arithmetic, enumeration, pointer, or pointer-to-member type and expression-list comprises exactly one expression, then the object is initialized to the (possibly converted) value of the expression (8.5);
— Otherwise the new-expression is ill-formed.

создаёт объект с помощью соответствующего конструктора. 

Это сообщение отредактировал(а) UnrealMan - 25.12.2008, 17:47
PM MAIL   Вверх
null56
Дата 25.12.2008, 18:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 2
Всего: 12



Блин, спасибо огромнейшее все стало ясно... 

По поводу других собственного operator new (мои параметры), чтобы new вызвал его, в смысле нашел... Нужно всего лишь вызвать сам new в соотвествии с правилами с правилами и тогда он сможет вызвать мой operator new и передать нужные параметры в соответствующей последовательности?

То есть, если я хочу, допустим передать своему operator new

Код

void * MyClass :: operator new (size_t size, std::string my_string) {}


Я должен в соотвествии с правилами сделать вызвать примерно вот так оператор new
Код

new ("my string") MyClass;


Где в роли expression-list будет ("my string")...

Надо просто поиграться и разобраться с правилами... но суть мне теперь ясна...

Спасибо еще раз
PM MAIL   Вверх
UnrealMan
Дата 25.12.2008, 19:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 27
Всего: 32



Цитата(null56 @  25.12.2008,  18:45 Найти цитируемый пост)
Я должен в соотвествии с правилами сделать вызвать примерно вот так оператор new

Если ты определишь функцию void * MyClass :: operator new (size_t, void *), то она и вызовется как более соответствующая вместо той, что с std::string. А если не определишь, то можешь столкнуться с проблемами, если вдруг захочется использовать такую функцию через new-выражение без ::


Это сообщение отредактировал(а) UnrealMan - 25.12.2008, 19:41
PM MAIL   Вверх
null56
Дата 25.12.2008, 19:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 2
Всего: 12



Да, это понятно... да и код такой не очень хороший.... это я в пример спросил

Спасибо огромное еще раз
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0982 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.