AMcoder - javascript, python, java, html, php, sql

նոր օպերատոր՝ դատարկ բացառության ճշգրտման կանչող կոնստրուկտորով, երբ հատկացումը վերադարձնում է 0

Ես ունեմ հետևյալ հայտարարությունը.

void * operator new (size_t s, PersistentMemory * m) throw()
   {return m->allocatePersistentMemory(s);}

Ես փորձարկում եմ հիշողության սպառումը գործարկման ժամանակ, ինչի արդյունքում m->allocatePersistentMemory(s);-ը վերադարձնում է 0: Նորը, այնուհետև կանչում է կոնստրուկտորին՝ զրոյական ցուցիչով this-ի համար:

Այնուամենայնիվ, C++ 2003 ստանդարտի 3.7.3.1 պարբերության 3-ի հիման վրա.

Բաշխման ֆունկցիան, որը չի կարողանում տեղաբաշխել պահեստը, կարող է կանչել ներկայումս տեղադրված new_handler-ը (18.4.2.2), եթե այդպիսիք կա: [Նշում. Ծրագրի կողմից տրամադրված հատկացման ֆունկցիան կարող է ստանալ ներկայումս տեղադրված new_handler-ի հասցեն՝ օգտագործելով set_new_handler ֆունկցիան (18.4.2.3): ] Եթե հատկացման ֆունկցիան, որը հայտարարված է դատարկ բացառության (15.4) հատկորոշմամբ, throw(), չի կարողանում տեղաբաշխել պահեստը, այն պետք է վերադարձնի զրոյական ցուցիչ: Բաշխման ցանկացած այլ ֆունկցիա, որը չի կարողանում տեղաբաշխել պահեստը, պետք է ցույց տա միայն խափանումը՝ բացառելով std::bad_alloc (18.4.2.1) դասից կամ std::bad_alloc-ից ստացված դասից:

Ես հասկանում եմ այն, որ m->allocatePersistentMemory(s) վերադարձնելը null պետք է հանգեցնի նրան, որ ամբողջ operator new() throw()-ը վերադարձնի null՝ առանց կոնստրուկտորին կանչելու: Արդյո՞ք ես բացակայում եմ որևէ այլ պայման, որը գերակայում է սա:

Շնորհակալություն


Պատասխանները:


1

Ես կասկածում եմ, որ դուք չեք զանգում newին, որը կարծում եք, որ զանգում եք:

Սա աշխատում է այնպես, ինչպես դուք ակնկալում եք:

void *myalloc (size_t) { return 0; }
void * operator new (size_t s) throw() { return myalloc(s); }
struct Foo {
    std::string s;
    Foo () { std::cout << this << std::endl; }
};
int main () {
    Foo *f = new Foo;
    if (f == 0) std::cout << "f is NULL" << std::endl;
}

Որտեղ, սա ձախողվում է:

void *myalloc (size_t) { return 0; }
void * operator new (size_t s) throw() { return myalloc(s); }
struct Foo {
    std::string s;
    Foo () { std::cout << this << std::endl; }
    void * operator new (size_t s) { return myalloc(s); }
};
int main () {
    Foo *f = new Foo;
    if (f == 0) std::cout << "f is NULL" << std::endl;
}
17.07.2012
  • Սա հայտարարված է որպես մակրոյի մաս, որը յուրաքանչյուր դասի սահմանման մեջ ներառում է նոր օպերատորի մասնագիտացված սահմանում, ուստի այս դեպքում գլոբալ operator new (size_t s, PersistentMemory * m) throw(); չկա: չնայած շնորհակալություն :) 17.07.2012
  • @shroudednight. Այնուամենայնիվ, հնարավոր է, որ այլ new օպերատոր է կանչվել: Տեղակայումը new, կամ new[] նույնպես պետք է ստուգվի: 17.07.2012
  • Շնորհակալություն լրացուցիչ մղման համար, դուք ճիշտ էիք: Մակրոն, որը ես ակնկալում էի, որ կսահմանվեր այս դասի համար, չէր օգտագործվում, փոխարենն ուներ իր հատուկ տարբերակը: 17.07.2012
  • @user315052. ինչու՞ երկուսն էլ լավ են աշխատում VS2010-ում: 13.10.2012

  • 2

    C++03 ստանդարտի 5.3.4 (13) բաժնում ասվում է.

    [Ծանոթագրություն. եթե բաշխման գործառույթը հայտարարված չէ դատարկ exception-specification (15.4), throw(), դա ցույց է տալիս, որ չի կարող տեղաբաշխվել պահեստ՝ նետելով bad_alloc em> բացառություն (կետ 15, 18.4.2.1); հակառակ դեպքում այն ​​վերադարձնում է ոչ զրոյական ցուցիչ: Եթե ​​հատկացման գործառույթը հայտարարված է դատարկ exception-specification, throw()-ով, այն վերադարձնում է null՝ նշելով պահեստի տեղաբաշխման ձախողումը, իսկ հակառակ դեպքում՝ ոչ զրոյական ցուցիչ: ] Եթե տեղաբաշխման ֆունկցիան վերադարձնում է զրոյական, սկզբնավորումը չպետք է կատարվի, ապա տեղաբաշխման ֆունկցիան չի կանչվի, և new-expression արժեքը պետք է լինի զրոյական:

    «Նախաստորագրումը չպետք է կատարվի» արտահայտությունը ենթադրում է, որ կոնստրուկտորը չի կանչվի:

    Հետաքրքիր է, և եթե ես սխալ չեմ կարդում սպեցիֆիկը, երբ ձեր հատկացման ֆունկցիան սահմանում է throw() և վերադարձնում null, «նոր»-ի կանչի արժեքը ինքնին զրոյական է: Ես միշտ մտածել էի, որ դա անհնար է (տես, օրինակ, գրեթե յուրաքանչյուր պատասխան Արդյո՞ք նորը ամեն դեպքում կվերադարձնի NULL-ը:): .

    17.07.2012
  • Շնորհակալություն լրացուցիչ հղումի համար: Այն միջավայրը, որտեղ ես աշխատում եմ, բացառություն է և ստանդարտ գրադարանային ֆոբիկ, փոխարենը՝ օգտագործելով jump buffers (setjmp) ¬.¬, որոնք հասանելի չեն այս պահին, ուստի ես զգալի խթան ունեի գտնելու այնպիսի աշխատանք, որն ամեն ինչ չփոխարինի առանձին հատկացումներով: , թեստեր և տեղաբաշխման նորություններ: 17.07.2012
  • Նոր նյութեր

    Օգտագործելով Fetch Vs Axios.Js-ը՝ HTTP հարցումներ կատարելու համար
    JavaScript-ը կարող է ցանցային հարցումներ ուղարկել սերվեր և բեռնել նոր տեղեկատվություն, երբ դա անհրաժեշտ լինի: Օրինակ, մենք կարող ենք օգտագործել ցանցային հարցումը պատվեր ներկայացնելու,..

    Տիրապետել հանգստության արվեստին. մշակողի ուղեցույց՝ ճնշման տակ ծաղկելու համար
    Տիրապետել հանգստության արվեստին. մշակողի ուղեցույց՝ ճնշման տակ ծաղկելու համար Ինչպե՞ս հանգստացնել ձեր միտքը և աշխատեցնել ձեր պրոցեսորը: Ինչպես մնալ հանգիստ և զարգանալ ճնշման տակ...

    Մեքենայի ուսուցում բանկային և ֆինանսների ոլորտում
    Բարդ, խելացի անվտանգության համակարգերը և հաճախորդների սպասարկման պարզեցված ծառայությունները բիզնեսի հաջողության բանալին են: Ֆինանսական հաստատությունները, մասնավորապես, պետք է առաջ մնան կորի..

    Ես AI-ին հարցրի կյանքի իմաստը, այն ինչ ասում էր, ցնցող էր:
    Այն պահից ի վեր, երբ ես իմացա Արհեստական ​​ինտելեկտի մասին, ես հիացած էի այն բանով, թե ինչպես է այն կարողանում հասկանալ մարդկային նորմալ տեքստը, և այն կարող է առաջացնել իր սեփական արձագանքը դրա..

    Ինչպես սովորել կոդավորումը Python-ում վագրի պես:
    Սովորելու համար ծրագրավորման նոր լեզու ընտրելը բարդ է: Անկախ նրանից, թե դուք սկսնակ եք, թե առաջադեմ, դա օգնում է իմանալ, թե ինչ թեմաներ պետք է սովորել: Ծրագրավորման լեզվի հիմունքները, դրա..

    C++-ի օրական բիթ(ե) | Ամենաերկար պալինդրոմային ենթաշարը
    C++ #198-ի ամենօրյա բիթ(ե), Ընդհանուր հարցազրույցի խնդիր. Ամենաերկար պալինդրոմային ենթատող: Այսօր մենք կանդրադառնանք հարցազրույցի ընդհանուր խնդրին. Ամենաերկար palindromic substring...

    Kydavra ICAReducer՝ ձեր տվյալների ծավալայինությունը նվազեցնելու համար
    Ի՞նչ է ICAReducer-ը: ICAReducer-ն աշխատում է հետևյալ կերպ. այն նվազեցնում է նրանց միջև բարձր փոխկապակցված հատկանիշները մինչև մեկ սյունակ: Բավականին նման է PCAreducer-ին, չնայած այն..