Почему оператор новой функции — форма размещения хорошо на уровне класса?

Мы знаем из стандарта c ++ 11 (также верно в стандарте c ++ 98/03) (см. Ниже), мы не можем попытаться заменить оператор новой функцией — помещением формы в глобальное пространство, как это уже было определено.

18.6.1.3 Формы размещения [new.delete.placement]

Эти функции зарезервированы, программа на C ++ может не определять функции, которые смещают
версии в стандартной библиотеке C ++ (17.6.4). Положения
(3.7.4) не применяются к этим зарезервированным формам размещения оператора новых
и оператор удаления.

Это было доказано пунктом 2> во фрагменте ниже, ошибка компиляции, как и ожидалось.

Но я все еще могу переопределить новое место размещения на уровне класса, которое отлично работает, см. Пункт (2) во фрагменте ниже. Это почему? Не следует ли компилировать, следует пытаться предотвратить (2), а также в соответствии со стандартом ???

Смотрите мой фрагмент ниже:

class Test
{
public:
Test(int i):m_i(i) { cout << "Test::Test()" << endl; }
~Test() { cout << "Test::~Test()" << endl; }

//(1)class level override placement new
void* operator new (std::size_t size) throw (std::bad_alloc) {
cout << "My class level new" << endl;
return malloc(size);
}

//(2)class level override placement new
void* operator new (std::size_t size, void* ptr) throw() {
cout << "My class level non-throwing placement new" << endl;
return ptr;
}
private:
int m_i;

};

//<1>global replacement for operator new - single object form
void* operator new (std::size_t size) throw (std::bad_alloc) {
cout << "My global new" << endl;
return malloc(size);
}//<2>global replacement for operator new - replcement  form
//NB. This is a attempt that definitely fails according to c++ stadnard:
//does get compile error: error: redefinition of 'void* operator new(std::size_t, void*)'
/*
void* operator new (std::size_t size, void* ptr) throw() {
cout << "My global non-throwing placement new" << endl;
return ptr;
}
*/

int main() {
Test* p = new Test(1);
delete p;

cout << "" << endl;
void* mem = operator new(sizeof(Test));
Test* p2 = new(mem) Test(1);
p2->~Test();
operator delete (mem);

return 0;
}

Ниже выводится, как и ожидалось:

My class level new
My global new
Test::Test()
Test::~Test()

My global new
My class level non-throwing placement new
Test::Test()
Test::~Test()

================================================== ================================
Дальнейшее уточнение моего вопроса:

18.6.1.3 Формы размещения Эти функции зарезервированы, программа на C ++ может не определять функции, которые заменяют версии в
стандарт Библиотека C ++ (17.6.4). Положения (3.7.4) не применяются к этим зарезервированным формам размещения

оператора new и оператора delete.

Это объясняет ожидаемую ошибку компиляции в точке <2> в моем фрагменте, так что это нормально.

Но почему я могу сместить формы размещения на уровне класса в точке (2) внутри пояснения класса?

3

Решение

§ 18.6.1.3 перечисляет следующие формы:

void* operator new(std::size_t size, void* ptr) noexcept;
void* operator new[](std::size_t size, void* ptr) noexcept;
void operator delete(void* ptr, void*) noexcept;
void operator delete[](void* ptr, void*) noexcept;

Правило, согласно которому «программа на C ++ не может определять функции, которые заменяют версии в стандартной библиотеке C ++», применяется только к этим четырем объявлениям функций, которые не находятся ни в одном пространстве имен. Если вы делаете свою собственную версию в классе или пространстве имен, это нормально.

На самом деле, иногда ты иметь обеспечить собственное размещение новых. Если вы объявите нормальный operator new в вашем классе он будет скрывать новое место размещения, предоставляемое стандартной библиотекой, и вам нужно будет добавить свое новое место размещения в классе, если вы когда-либо захотите использовать new (ptr) T(...) синтаксис.

Это просто гарантирует, что звонок ::new (ptr) T(...) является гарантированный вести себя как стандартное размещение нового. (Обратите внимание :: префикс.)

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]