Как стать автором
Обновить

Комментарии 40

Есть замечание по терминологии.
Для начала опеределимся с терминологией — далее именуемый в стандарте new-expression я буду называть «оператор new» (...), а operator new я так и буду называть operator new. (...)

оператор new — это оператор языка, такой же как if, while и т.д. (хотя if, while и т.д. все же именуются как statement, но отбросим лирику)

Во-первых, отличить на глаз «оператор» от «operator» в потоке текста очень сложно (особенно тем, кто много читает на английском). Во-вторых, раз уж вы пытаетесь рассмотреть разницу между этими понятиями, называть их одним и тем же словом неразумно. Можно окончательно запутать читателя. Конечно, и statement можно перевести как «оператор», но лучше не надо. Это не «лирика», а важное различие на уровне компилятора. (Пишу не в личные сообщения, потому что вопрос спорный и подлежит обсуждению.)
Можно было, например, опустить слово «оператор/operator». Все равно дальше по тексту одна из форм всегда используется со скобками, другая — без них.
Согласен, исправлю.
В наиболее распространенном русском переводе «The C++ Programming Language» этой теме был посвящен довольно-таки большой параграф во вступлении от переводчиков. В той книге они использовали для перевода «statement» слово «инструкция». Я думаю, достаточно большое количество русскоговорящих разработчиков на C++ начинали именно с этой книги, или, во всяком случае, читали её на каком-то этапе — так что в плане терминологии её можно использовать как некоторого рода стандарт.
Статья конечно может «как-то» помочь новичкам.
Но! Не знаю о каких книгах вы говорите (судя по всему о дейтелах и им подобных), но в Мейерсе, Саттере, Дьюхерсте, Вилсоне и даже в Джосютиссе (не представляю какие еще книги по С++ можно читать, ну кроме Страуструпа конечно) четко разделяется оператор new от выражения new.
Думаю (это критика, которую вы хотели) вы просто только что открыли для себя Америку и хотели раксрыть «заговор» всему миру, но мир еще десять лет назад знал об этом ка свои пять пальцев.

P. S. Ставлю плюс, чтоб не разбить стремление к sharing-у знаний.
>Не знаю о каких книгах вы говорите
Я же написал «в книгах для начинающих»
За критику спасибо, но не каждый С++'ник может «на пальцах» объяснить где и как вызывается конструктор при использовании new, поэтому
>мир еще десять лет назад знал об этом
считаю не совсем уместным. Мир то знал, а вот некоторые программисты до сих пор не знают)
:) Теперь будут знать, и еще будут знать какие книги читать ;)
не каждый С++'ник может «на пальцах» объяснить где и как вызывается конструктор при использовании new, поэтому

Этими знаниями можно блеснуть на собеседовании (но мне такой вопрос ни разу не задавали и я кажется знаю почему), но какой от них практический толк?

Ну вот не знаю я (или просто забыл) что operator new != keyword new, но я примерно помню (читал не раз) как переопределяется свой operator new. А теперь я знаю (вспомнил) что operator new != keyword new… и… ничего не изменилось, я все еще не знаю накой мне это может понадобится и тем более на какие грабли при этом я встану (я ведь знания как правильно переопределять operator new гораздо важнее чем знания, что operator new != keyword new).

Какой профит?
Какой профит?

В прикладном плане никакого. Но неужели не хочется знать чуть больше, чем необходимо? :)
А если включить мозг? И вспомнить, что и глобальный оператор можно только заменить, а локальный перегрузить как угодно?
А какое отношение это имеет к написанному в статье?
Трампарарам., вы говорите не знаете как применить на практике различие межу кейвордом и оператором. А я уже говорю, что оператор можно перегрузить как угодно. Уже только из этого вытекает масса различным применений.

А если заменить реализацию кейворда на свою, а оператор не трогать? А если сделать и то и другое?
Как вы кейворд переопределите? Единственный способ — это взять исходники компилятора, подправить там код обработки new и скомпилировать свой компилятор.
> но мир еще десять лет назад знал об этом ка свои пять пальцев

тридцать лет назад :-)
Время летит… :)
Можно Джефферсона еще почитать) А об авторах, которых Вы перечислили даже не слышал, ну кроме Страуступа, конечно)
Имхо проще в русском тексте так и писать — «new-expression» и «operator new» вместо «оператор» и «operator».
Да, подумал и исправил именно на этот вариант.
Прочитав про две разные сущности, ожидал дальше увидеть два разных примера применения каждой из них. Но не увидел. Как можно воспользоваться этим различием между new-оператором и new-ключевым словом в процессе разработки?
Не помню где точно, но вроде бы на Хабре проскакивала эта ссылка — там описывают разницу между «оператором new» и «new оператором» :)
Прочитав про две разные сущности, ожидал дальше увидеть два разных примера применения каждой из них.

Эм, здесь речь немного не об этом, пример реализации operator new() можно найти в любой книге, поэтому я не стал его включать в статью.
Как можно воспользоваться этим различием… в процессе разработки?

В процессе разработки, думаю, никак. Просто такие вещи полезно знать и понимать хотя бы для самого себя.
Как это нигде? А как же placement new?
char buf[10]; Foo * f = new(buf) Foo(123); — как раз и будет пример new-expression.
Ну не знаю, я бы привёл реализацию operator new (msvc10):
_C_LIB_DECL
int __cdecl _callnewh(size_t size) _THROW1(_STD bad_alloc);
_END_C_LIB_DECL

void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
        {       // try to allocate size bytes
        void *p;
        while ((p = malloc(size)) == 0)
                if (_callnewh(size) == 0)
                {       // report no memory
                static const std::bad_alloc nomem;
                _RAISE(nomem);
                }

        return (p);
        }

становится ясно, что operator new просто выделяет память, причём тем-же malloc — при неудачном выделении памяти — вызывает new_handler функцию и только потом (если ничего не изменилось) бросает исключение.
1. Нигде не разделяют new key-word языка С++ и оператор new, везде о них говорят как об одной сущности.
Как это нигде, Мейерс разделяет, стандарт разделяет :-)
Ну и мы с вами :)
Под «нигде» я подразумевал книги для начинающих.
Кстати, похожая ситуация с operator ->() и оператором ->, который для пользовательских типов преобразуется в:
(object.operator ->())->member
Читаем «C++ For Real Programmers» (Jeff Alger) и ещё много нового о работе с памятью.
А при чем тут работа с памятью?
Для гибкой работы с памятью дали возможность перегрузить operator new
habrahabr.ru/post/148657/
Ну это да, как и delete. Просто в статье речь не о работе с памятью и не об использовании new / delete.
Ну, new и operator new() предназначены — внезапно — для управления памятью. А в книге, которую я порекомендовал, помимо озвученного в статье материала, есть ещё куча информации об этих сущностях, а также об управлении памятью в C++ вообще. Информация в статье интересная, но сама по себе бесполезная, вот книга и даст остальную информацию, необходимую для того, чтобы, например, реализовать сборку мусора и дефрагментацию памяти.
Вроде банальный момент, который сразу всплывает когда в коде встречаются 'new int' и 'new Foo'.
Да неужели?

int* p = new int(10);//как бе сконструировали инт
Foo* p_foo = (Foo*)malloc(sizeof(Foo));//ниче не конструировали
new(p_foo) Foo(19, false,«description»);//вау — обьект сконструировался!
у кого-нибудь корректно получалось в своей жизни хоть раз использовать placement syntax new для массивов?
у меня он так и не стал добавлять нужные оверхеды и пришлось везде юзать обычный placement syntax внутри цикла.
А в чем проблема? У меня вроде все работало.
грубо говоря как то так работало:
T* pNew = (T*)m_BasicCallback->malloc_cb(sizeof(T)*size,1);
//copy old elements
T* raw_i = pNew;
int i=0;
for(;i<m_Size;++i,++raw_i){
raw_i = new (raw_i) T(m_pData[i]);
}

а вот какую-то запись которая бы и память корректно выделила и конструкторы для всех экземпляров массива вызвала не получилось. вариант для массивов памяти выделял почему-то меньше чем было нужно.
Хм, вот такой пример:
 char *ptr = (char*) malloc(10);
    memset(ptr, 1, 10);

    char* ptrPlacement = new(ptr) char[10];
    ptrPlacement[9]=10;
    free(ptr);

Проблем в упор не вижу (Ну кроме того, что если вместо char будет класс, то придется делать прямой вызов деструктора, а потом делать free)
Для динамически созданной группы обьектов нельзя применять конструктор с параметрами.
Спасибо большое за статью! Для меня этот вопрос с оператором new создал путаницу в голове. Теперь все стало ясно.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории