-5

I am new to c++, I wanted to know how to return null if a condition. Also, wanted to know what is the best practice in these occasion because I could just create this function by knowing not to call if the condition is not met, but usually with C#, Java, Javascript, and other OOP we do checks before returning due to invalid values. Please keep in mind I work with a really old cpp compiler. Example:

MyObject MyObject::createObject(int id){
       if(id < 0) return nullptr;
      return new MyObject(id);
}

Edit: I had a really on C++ compiler which does not accept C++11 or above. Please don't be rude on the criticism. It's just that I am stuck with old compilers and can't do anything about that one. I do not want to return a pointer because that will be more mess to go with. I just would like to know what could be done and/or what will be the best practice for this issues. Thank you in advance!

Edit 2: After finding out nullptr was something that was not declared in old version of c++, I had to use NULL to be able to return nullptr since the error kept saying it was not declared.

My answer looked like:

MyObject MyObject::createObject(int id){
       if(id < 0) return NULL;
      return new MyObject(id);
}
Recursive
  • 211
  • 3
  • 10
  • 2
    you cannot. You can only return a `MyObject` – 463035818_is_not_an_ai Jun 09 '23 at 18:41
  • 1
    @Recursive: 463035818_is_not_a_number is correct. Ezbob's reply below explains *WHY* this is the case. Please consider "upvoting" and "accepting". – paulsm4 Jun 09 '23 at 18:54
  • 2
    @πάντα ῥεῖ of course, that's why I am asking – Recursive Jun 09 '23 at 19:23
  • 2
    That's the truth. I do note that you have been asking a lot of questions that are based on a fundamentally flawed understanding of C++. Whatever you're using as teaching materials is terrible, and I recommend exchanging it for [a good book or two](https://stackoverflow.com/q/388242/4581301). – user4581301 Jun 09 '23 at 19:30
  • Thank you , I'm so confused on pointers. I'll take a look at your link – Recursive Jun 09 '23 at 19:36
  • 5
    A long time ago, after computer science and early in electrical engineering, I had to take yet another C programing course. The instructor, an engineer, didn't cover pointers. When I asked him why he said, "I don't need them." Turned out to be one of the best teachers I ever had. – user4581301 Jun 09 '23 at 19:39
  • @user4581301 wish they were all like that `:\ ` – underloaded_operator Jun 09 '23 at 21:52
  • @user4581301 after all the replies I came up with a solution and I've got rid of pointers. I will try to avoid 'em at all cost lol after I did that I advanced more now. I 101% agree with your instructor after this. – Recursive Jun 09 '23 at 22:30
  • 2
    Don't go too far on No Pointers. The real problem isn't with pointers, it's with A) overusing pointers and B) managing dynamic allocations. A is usually handled by asking, "Does this make my code more or less complicated?" and being honest with yourself. Takes a bit of experience. B is solved with a hierarchy. Prefer automatic allocation over [smart pointer](https://learn.microsoft.com/en-us/cpp/cpp/smart-pointers-modern-cpp?view=msvc-170) or [library container](https://en.cppreference.com/w/cpp/container) when you have more than one, over `new`/`new[]`, over `malloc`. – user4581301 Jun 09 '23 at 22:50
  • [This answer](https://stackoverflow.com/a/22122095/4581301) is one of my favorite examples of when to use an extra pointer. When you're working on a linked list, you're pretty much stuck with pointers, but here you can use a pointer to a pointer to hide the one difference between the head pointer and a next pointer (the name) and eliminate a bunch of code and with a pointer to the next pointer, you have one variable tracking where the item goes (and don't need a prev pointer) and where the next item is at the same time! Only two conditions that need testing rather than 3. – user4581301 Jun 09 '23 at 23:01
  • @user4581301 thanks a lot for that. I edited my question because looks like if I didn't put a little more info into why there's limitation on my side I would sound like a completely maniac trying to do something that is not recommended. It is just my limitations I have. I don't really do C++, my specialty are others, this is just something I had to do for this time. – Recursive Jun 24 '23 at 22:16

2 Answers2

3

You can return std::optional since C++17

std::optional<MyObject> MyObject::createObject(int id) {
  if (id < 0)
    return {};
  return MyObject{id};
}

Or std::expected sine C++23

enum class error {
  invalid_arg
};

std::expected<MyObject, error> MyObject::createObject(int id) {
  if (id < 0)
    return std::unexpected(error::invalid_arg);
  return MyObject{id};
}

You can use std::pair prior C++17, the perfect example of the such usage is std::map::insert, but you have to always return some default object MyObject.

std::pair<MyObject, bool> MyObject::createObject(int id) {
  if (id < 0)
    return std::pair<MyObject, bool>();
  return std::pair<MyObject, bool>(MyObject(id), true);
}

Or a pointer instead of a pair

MyObject* MyObject::createObject(int id) {
  if (id < 0)
    return 0;  // No nullptr until C++11
  return new MyObject(id);
}
273K
  • 29,503
  • 10
  • 41
  • 64
  • This is a better answer, but if you prefer to return a pointer, make it a `std::unique_ptr` – Paul Sanders Jun 09 '23 at 19:15
  • It's a better solution, but it's lacking an explanation of why the asker can't do what they tried. That's a one-liner, so might as well add it for completeness. – user4581301 Jun 09 '23 at 19:17
  • @273K looks like I was using a really old version of c++ which did not accept the keyword nullptr. Sorry for that. It only accepts NULL – Recursive Jun 24 '23 at 22:10
2

The return type MyObject is not a pointer type here so you cannot use nullptr here. This is because nullptr is a pointer. You should do something like this:

MyObject * MyObject::createObject(int id){
   if(id < 0) return nullptr;
   return new MyObject(id);
}

instead.

Note: the asterisk in the return type.

paulsm4
  • 114,292
  • 17
  • 138
  • 190
Ezbob
  • 329
  • 1
  • 9
  • nullptr is not declared so I used NULL is that correct? – Recursive Jun 09 '23 at 19:14
  • 1
    @Recursive • if the compiler is complaining about `nullptr`, you are compiling with a very old C++ standard. I recommend C++17 or higher these days. – Eljay Jun 09 '23 at 19:17
  • 1
    @Recursive You can use `NULL` here instead of `nullptr`, yes, but now I am curious what C++ standard are you compiling your code for? – Ezbob Jun 09 '23 at 19:18
  • is for linux, really old. sorry for limitations on my part – Recursive Jun 09 '23 at 19:19
  • @Ezbob how would I cast MyObject* to MyObject myObject; and could there be any loss of data? or just treat it normally – Recursive Jun 09 '23 at 19:20
  • Note: This answer forces management of an object with dynamic scope onto you. Don't use it without good reason. – user4581301 Jun 09 '23 at 19:21
  • A pointer to an object is not that object. You can't safely cast it. They are fundamentally different things. It would be like trying to live in a sheet of paper with the address of a house written on it. – user4581301 Jun 09 '23 at 19:22
  • 4
    Since it looks like modern C++ is off the table, return a `std::pair`. Set the `bool` in the pair to true if you can return an object and to false if you can't. – user4581301 Jun 09 '23 at 19:23
  • @Recursive you can dereference it also using *, but if you bind it to a variable by doing `MyObject *o = MyObject::createObject(42); MyObject o2 = *o;` then you will have made a copy of the data in `o` to `o2`, potentially wasting memory space. This gets worse if `MyObject` contains any pointers as member values, as these will be copied too, so they will point to the same objects. I would advise that you follow @user4581301's advice here, and act as they are incompatible types. – Ezbob Jun 09 '23 at 19:30
  • 1
    Note that after you `MyObject o2 = *o;`, you still must `delete o;` to release the object `o` points at before `o` is allowed to go out of scope and you can no longer easily find the object in order to release it. Most definitely do not `MyObject o2 = *MyObject::createObject(42);` Because without that pointer, you are stuck with the object it pointed at floating around taking up resources until the program ends and the operating system reclaims all of the processes resources. Assuming you have an operating system, of course. – user4581301 Jun 09 '23 at 19:35
  • @user4581301 looks like the issue was I was in an old c++ compiler which caused nullptr keyword to not be declared. I was able to figure that out. Thanks for the links, I was able to get a hold of a book too which helped me out. I kinda get confused other programming languages with cpp. C++ is a different monster compare to other OOP – Recursive Jun 24 '23 at 22:13
  • C++ is a generalist language. It supports OOP, but it's not the only tool in C++'s bag of tricks. You get a lot of versatility, but sometimes the optimal path flies in the face of OOPs recommendations. – user4581301 Jun 26 '23 at 15:03