На самом деле, есть простое решение: замените оператор new на оператор, который выдает ошибку при выделении. (Связанный код является стандартным C ++ и может потребовать настройки для вашего компилятора. Вы можете использовать malloc для allocate_from_some_other_source и бесплатную для deallocate_from_some_other_source.)
Старый ответ
(Эти замены требуют изменений в вызывающем коде просто потому, что грамматика C ++ структурирована таким образом, что это неизбежно. Однако они написаны так, чтобы требовать минимальных изменений, чтобы их можно было использовать в качестве логических вставных замен. Настоящее решение - обновление до версии MSVC за последние 7 лет или около того. MSVC6, который, как кажется, вы используете, был фактически выпущен до стандарта C ++ в 1998 году.)
Решить для общего случая сложно, но вот приближение:
struct Thrower { // needs a better name
void* p;
Thrower(void* p) : p(p) {
if (!p) throw std::bad_alloc();
}
~Thrower() {
if (std::uncaught_exception()) operator delete(p);
// this is true when the object's ctor throws
}
operator void*() const { return p; }
};
int main() {
int* p = new (Thrower(operator new(sizeof(int))) int(42);
// int is a placeholder type, but shows you can still pass ctor parameters
// with a macro becomes:
#define MYNEW(T) new (Thrower(operator new(sizeof(T))) T
int* p = MYNEW(int)(42);
}
Для известных параметров вы можете избежать макроса и сделать его простым:
template<class T>
T* my_new() {
T* p = new T();
if (!p) throw std::bad_alloc();
return p;
}
template<class T>
T* my_new(T const& value) {
T* p = new T(value);
if (!p) throw std::bad_alloc();
return p;
}
int main() {
int* p = my_new<int>();
int* p2 = my_new<int>(*p);
}