0

i was writing a class like this

class AA{
private:
    char* str;
public:
    AA(int size){
        str = (char*)malloc(size);
    }
};

int main(){
    AA anAA(1000);
}

here is the problem, when the size is too big it may cause malloc return a 0 pointer, if the str init fail, is there any method to return a 0 pointer to anAA(in the main entry point, i can check anAA isn't init success by if(anAA != NULL)), i don't want to make a function for creating AA class, or make a check function in the class

Roy C
  • 25
  • 4
  • 4
    Why are you allocating your own `char*` strings instead of using `std::string`? – James Adkison Mar 24 '16 at 06:02
  • Similar: http://stackoverflow.com/questions/4989807/how-to-handle-failure-in-constructor-in-c – andars Mar 24 '16 at 06:02
  • 7
    Don't use `malloc` et al in C++, use `new` and `new[]` instead, ***if*** (and only if) you must use pointers. Those will throw exceptions when they fail to allocate memory. But instead of pointers and `new`/`new[]` I suggest you use [`std::vector`](http://en.cppreference.com/w/cpp/container/vector) instead. – Some programmer dude Mar 24 '16 at 06:03
  • This is why I keep saying RAII is an illusion in C++. If you have things that can fail in the constructor, better go 2 stage init. Constructor only creates a consistent state but does nothing dangerous. Then, have an ``Init(size_t size)`` which can either throw or return an error value. – BitTickler Mar 24 '16 at 06:05
  • 2
    @BitTickler 2-stage init leads to the possibility of zombie objects existing. This is annoying and makes your code less elegant because you have to check for zombie objects everywhere. IMHO it should be avoided unless there is no way to avoid it without committing an even greater evil. – M.M Mar 24 '16 at 06:11
  • oh thanks, i think the init function is a good way, thanks a lot – Roy C Mar 24 '16 at 06:17
  • Why don't you throw an exception if allocation fails? – Jean-Baptiste Yunès Mar 24 '16 at 06:29
  • @BitTickler That would be doing it wrong. The idiomatic way is to throw. – juanchopanza Mar 24 '16 at 06:30
  • Do unhandled throws in constructors not terminate the program? Well... I am embedded guy. Cannot risk that... – BitTickler Mar 24 '16 at 07:57
  • @BitTickler: No, not at all. The compiler will undo member construction, and give the caller the chance to handle it in turn. And as an embedded buy, you should have a global `catch(...)` which resets the device. That's much safer than continuing to run with an unexpected, ignored error which leaves your device in an unknown state. – MSalters Mar 24 '16 at 09:11
  • unm..i don't want to throw exception is because it is a set of library i will use in future, i afraid that i forgot to catch exception when i call those function, and catching exception is really not convenience, so i try to avoid throw exception – Roy C Mar 25 '16 at 09:15

2 Answers2

0
#include <iostream>
#include <stdexcept>   // std::exception
#include <stdlib.h>    // EXIT_FAILURE
#include <string>      // std::string
#include <vector>      // std::vector
using namespace std;

class AA{
private:
     string str_;
public:
    AA( int const size)
    {
        str_.reserve( size );
    }
};

int main()
{
    try
    {
        AA anAA( 1000 );
        // Whatever
    }
    catch( exception const& x )
    {
        cerr << "!" << x.what() << endl;
        return EXIT_FAILURE;
    }
}

Note 1: with this approach you probably don't need to reserve a size upfront.

Note 2: I chose reserve as probably the closest thing to a presumed intention of making sure that str_ can hold at least that long a string without failure, a preallocation of resources.

Disclaimer: I've not compiled this code.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
0

I'll ignore the atrocities you are committing in favour of answering your question.

The easiest solution, if you don't want to use exceptions, is to define an operator bool():

class AA{
    ...
public:
    operator bool() const {
        return this->str != nullptr; // return str; would actually suffice
    }
};

int main(){
    AA anAA(1000);
    if (!anAA) {
        std::cerr << "Creating object failed.\n";
        return 1;
    }
    return 0;
}
kamikaze
  • 1,529
  • 8
  • 18
  • It's ungood to teach zombie objects to a beginner. That way leads to the dark side. – Cheers and hth. - Alf Mar 24 '16 at 09:09
  • @Cheersandhth.-Alf I don't think they can always be avoided. And I usually prefer answering the question over lecturing. Or at least, answer first, lecture later. Because even knowing how to do it wrongly improves understanding of the language. – kamikaze Mar 24 '16 at 12:42
  • @Cheers and hth. - Alf oh god, that is exactly what i am looking for, but why you don't recommend the zombie object? after i check the object create isn't success, if not, just delete it, why don't? – Roy C Mar 25 '16 at 09:35
  • @RoyC: It's too easy to use incorrectly, and it adds ridiculous complexity for no (or actually negative) advantage. The approach was still used, for reasons that still made sense at the time, in the middle 90's. But that was the last of it. If you want some reading then I suggest you start with Bjarne Stroustrup's discussion of exception safety in the standard library, in an appendix to the 3rd edition of "The C++ Programming Language". http://www.stroustrup.com/3rd_safe0.html – Cheers and hth. - Alf Mar 25 '16 at 09:57