What would I want to use instead of NULL if I have an unassigned pair in C++?
As an example, suppose I have (pseudo)code like the following:
pair<int,int> bestPair; //Global variable
updateBestPair(vector<int> a, vector<int> b) {
bestPair = NULL;
for (/* loop through a and b */) {
if (/* pair(a,b) is better than bestPair and better than some baseline */)
bestPair = make_pair(a,b);
}
if (bestPair != NULL) //Found an acceptable best pair
function(bestPair);
else
cout<<"No acceptable pairs found"<<endl;
}
Is there a NULL equivalent for pairs in C++?
No.
What would I want to use instead of NULL if I have an unassigned pair in C++?
Here are a few options:
you can use a pointer to a pair, which can be set to NULL; This is probably not the best solution (since you are clearly not requiring a pointer)
you can use a boost::optional<std::pair<int,int>>;
you can (and probably should) rewrite your code not to use a global variable.
you can restructure your control flow to avoid checking for a valid pair as a separate step:
pair<int,int> bestPair; //Global variable
updateBestPair(vector<int> a, vector<int> b) {
// not needed
// bestPair = NULL;
//loop through a and b
if (/* pair(a,b) is better than bestPair and ... */)
{
bestPair = make_pair(a,b);
function(bestPair);
}
else
cout<<"No acceptable pairs found"<<endl;
}
you can choose an artificial value to represent "invalid pair value":
// use as constant, wherever you used NULL before
const auto invalid_pair = std::make_pair(
std::numeric_limits<int>::max(),
std::numeric_limits<int>::max());
you can use a boolean flag:
pair<int,int> bestPair; //Global variable
updateBestPair(vector<int> a, vector<int> b) {
bool initialized = false;
//loop through a and b
if (/* pair(a,b) is better than bestPair and ... */)
{
bestPair = make_pair(a,b);
initialized = true;
}
if(initialized)
function(bestPair);
else
cout<<"No acceptable pairs found"<<endl;
}
you can use a custom solution (similar to boost::optional wrapper or not)
No. C++ objects cannot be "NULLed".
(Even pointers, which are objects, cannot be "NULLed"! This is confusing because their value may be set to a null pointer value, which we sometimes in the past obtained with a macro named NULL; however, this has never been the same as "NULLing" the pointer itself. Er, anyway…)
I recommend either boost::optional, or rethink the idea of having a global variable that can be "has a useful value" or "does not have a useful value". What's the point in it existing if it has no useful value?
No, that is not possible. You could use an additional variable to indicate the validity of the pair (that you have a pair).
Related
I'm newbie and I need little help.
I tried different ways, but from what I can see NULL means 0 in c ++, so when want my (for example) int arr[4]=0, then it says that it's also NULL. Is there any way to see when value is 0 and not NULL (or empty?).
Sounds like a job for std::optional:
#include <iostream>
#include <optional>
int main()
{
std::optional<int> arr[] = { 10, 0, std::nullopt, -52 };
for (auto i = 0U; i < sizeof(arr) / sizeof(*arr); i++)
{
if (arr[i])
{
std::cout << "arr[" << i << "] = " << *(arr[i]) << std::endl;
}
else
{
std::cout << "arr[" << i << "] = std::nullopt" << std::endl;
}
}
}
Output:
arr[0] = 10
arr[1] = 0
arr[2] = std::nullopt
arr[3] = -52
It sounds like you're looking for a null concept for your data type (int array[4]), but you want 0 to be a valid (non-null) value. The null concept is useful when your variable is not guaranteed to hold valid data. You need a null concept if, for a variable x, you want to be able to ask the question "does x contain a valid value?".
First, recognize that NULL is an implementation-defined way to represent a pointer that points at nothing. Here, implementation means "specific compiler". Usually, NULL is an integer constant equal to 0, which in practice makes it ill-suited to differentiate from your otherwise-valid value of 0.
TL;DR: I think you want to use std::vector, but you have several options available.
Null concept for int
Depending on what your data represents, you may be able to represent a null by selecting a value or range of values that are not valid for your specific use case, but otherwise representable using your data type.
Some example null concepts for int data type:
0-- is a perfectly fine null when 0 is not a valid value. The null test code is very clean as well: if (x) { ... }.
negative values-- You can select a specific negative value or the entire range of negative values. Or even a subrange of all negative values, although I've never seen this last one in practice. Generally the specific value of -1 is used. The null test code looks like: if (x >= 0) { ... } or if (x != -1) { ... }.
extreme positive values-- You can select a very large number to represent the null concept. If a valid instance of your data will never reach this value. I recommend std::numeric_limits<int>::max(), which requires #include <limits>. The null test looks like: if (x != std::numeric_limits<int>::max()) { ... }
std::optional<T>
When all possible values of your data type represent valid values, then you need to include extra overhead if you want to represent the null concept. std::optional<T> wraps any data type and is used specifically for the case where you need to represent invalid data. The access semantics looks very similar to accessing a pointer.
#include <optional>
void do_something(int);
int main() {
std::optional<int> a; // default initialization is "empty"
std::optional<int> b = 1; // can be assigned just as if it were the type
if (a) { // You can check in a natural-feeling way if the data is valid
do_something(*a); // and access the data as if it were a pointer
do_something(a.value()); // or use std::optional<T>::value()
}
// If the data may be invalid, you must check before accessing
// *a; // WRONG: throws an exception
// a.value(); // WRONG: for the same reason
// If you know for certain the data is valid, feel free to access it
do_something(*b);
// You can't access it entirely as if it were an int, dereferencing is necessary
// int c = b + 2; // invalid, no overloaded operator+ for std::optional<int> type
int c = *b + 2; // valid
// An array of optionals looks similar to an array of ints
std::optional<int> array[4]; // initialized as all empty
Just don't deal with invalid data at all
If your data doesn't necessarily need to exist until it is valid then you can use a variable size container to just... not have invalid data at all.
std::vector<T> is the go-to dynamically sized container in C++, and allows you to have just enough space to handle only the data you need. std::vector<T> also has many class methods that allow easy access to container information such as std::vector<T>::size() or iterators with std::vector<T>::begin() and std::vector<T>::end().
#include <vector>
void do_something(int);
int main() {
std::vector<int> data; // initially empty, no elements
// you can add new values
data.push_back(1); // vector contains { 1 }
data.emplace_back(2); // vector contains { 1 , 2 }
// looping is the same as with arrays
for (int i = 0; i < data.size(); i++) {
do_something(data[i]);
}
// or you can use range-based for loops for cleaner looking code
for (auto& d : data) {
do_something(d);
}
}
If that is an array of pointers:
int* arr[10] = {};
Then here is how you check if an element is null:
if (arr[4] == nullptr)
And here is how you check if the pointed value is zero:
if (*arr[4] == 0) // note the *
I have a method, which i want to execute differently depending on if the passed variable is an element of a vector or not, like for example:
void method(int a){
if (/*a is an element of a vector*/) //do one thing
else //do another thing
}
and then in main:
vector<int> a;
a.pushback(1);
int b = 1;
method(a[0]); // does one thing
method(b); // does the other thing
What is the simplest way to do that?
Well, for all cases this is impossible, because it actually requires your function to look at how it is executed, and there is no such thing in C++. The hated eval() comes to mind.
But in a certain case, when your vector is a global entity, you could pass your variable by link instead of value. Then, you can check if it fits the space between the start and end of the desired vector. This is how it is done(not tested though, but should work)
vector<int> v;
//fill it somewhere somehow
void method(int& a)
{
int* beg = v.data();
int* end = beg + v.size();
int* val = &a;
if ((val >= beg) && (val < end))
{
//it is a part of vector
}
else
{
//it is not a part of vector
{
}
Problem is that you really shouldn't do it this way... As people in the comments said, it DOES look like an XY problem.
An int is an int. An int does not wear a label around its neck, telling everyone where it came from. When an int is passed to a function, there is nothing that specifies where the int originates.
You should take this as an opportunity to learn about iterators, and implement an overloaded method that takes either an
void method(int);
for a parameter, or a
void method(std::vector<int>::iterator iter);
for a parameter (or, perhaps, a const_iterator), and invoke the alternative method() by passing it an iterator to the int in your vector.
** Please don't criticize the purpose of the code itself. It's from Pat Morin's Open Data Structures book. Not my first choice, its assigned reading/practice. I just wanted to know if there is a way to differentiate, or a better way to go about this. Textbook--> http://opendatastructures.org/ods-cpp/**
** Another note: I'm coming from Java, where this would be allowed. My code still compiles, it just "fixes" it**
I'm surprised nothing like this has come up before because it seems like such a simple question. Perhaps it's buried or I'm not using the correct terminology.
I have a for loop that goes through the data in a vector. I need to return the value being searched for if it's found. What if it's not found? Here is my code.
int find(int x) {
for(int i=0;i<bag.size();i++){
// if x is equal to data, return data
if (bag[i]==x){
return bag[i]; // ends loop as soon as one instance is found
}
}
// if we made it this far, no match was found.
return NULL;
}
Pretty simple. Let's say 0 is one of the valid values that I might need to record and search for. As it is, it actually returns 0, not "NULL". Research says it is one and the same. How can I specify or differentiate? Other than returning an obsqure number that won't come up in the program because we may not always have that luxury (like -1 or -9999999). For example, searching for your account balance. No number is impossible.
Why would you return the value you are searching for from a find function? You already know the value, its the one you passed to the function. Return the position of the found element instead, as this information is much more useful. When the value isn't found, you can return a special position, like -1. Or you can follow the model of the standard library and return the end iterator, which signifies a position that is one past the end of the range.
You can write the function in several ways
bool find( int x )
{
std::vector<int>::size_type i = 0;
while ( i < bag.size() && bag[i] != x ) i++;
return i != bag.size();
}
Or
std::vector<int>::size_type find( int x )
{
std::vector<int>::size_type i = 0;
while ( i < bag.size() && bag[i] != x ) i++;
return i;
}
Or
#include <algorithm>
//...
std::vector<int>::iterator find( int x )
{
return std::find( beg.begin(), bag.end(), x );
}
And use the functions correspondingly the following ways
if ( find( x ) ) { /*...*/ }
if ( find( x ) != bag.size() ) { /*...*/ }
if ( find( x ) != bag.end() ) { /*...*/ }
As for your general question in the title of the post
What if I need to differentiate 0 from NULL in C++?
then you need fo use nullptr instead of NULL that to differentiate 0 from NULL.:)
#define XOR_MSB(x) (x^0x80000000)
int find(bool found) {
return found ? XOR_MSB(0) : NULL;
}
int main()
{
int value = find(false);
if (value == NULL) printf("not found\n");
else printf("%d\n", XOR_MSB(value));
value = find(true);
if (value == NULL) printf("not found\n");
else printf("%d\n", XOR_MSB(value));
return 0;
}
you're talking about an evil practice, coming from Java and C# developers where you can return null as invalid result.
well, you can't do it in C++.
Java and C# declares almost everything on the heap, and accessing objects is done done always by the reference. this means you always return a pointer from a function, and you can always return a null as a return value.
this is not so possible in C++ when a function does not return a pointer. for example , the function std::string returnString() can't return null as a return value.
more over, you should not return null as invalid output. this is wrong on so many levels even in C# and Java! if your function fails, simply throw an exception, or make your return value be passed as reference-argument and make the function return true or false.
you can also find less-agressive solutions like returning -1 (like indexOf() in javascript) or return somthing like std::string::npos or std::vector:end which are more C++ STL tuned.
This is what boost::optional<T> is for. Effectively, this type represents "There may be a T, but there may not be a T". The user may check if there is a T or not. Ideally you would not depend on any special value of T but use an optional<T> instead. optional<T> is fully generic and may apply to pretty much any T you may need to use, it does not depend on some special value or state of T.
boost::optional<int> find(int x) {
for(int i=0;i<bag.size();i++){
// if x is equal to data, return data
if (bag[i]==x){
return bag[i]; // ends loop as soon as one instance is found
}
}
// if we made it this far, no match was found.
return boost::none;
}
int main() {
if (auto opt = find(5))
std::cout << *opt;
}
Do not ever use NULL, it is a terrible thing. Always use nullptr which is substantially safer and one of the reasons why it is safer is because your wrong code would not compile.
We have got legacy code which returns huge sized lists of raw pointers to heap allocated objects (we can't use smart pointers), and we'll remove duplicates from the list and also delete them from heap.
For now, as it advised by gurus, I would like to try std::list::unique (or forward_list::unique) instead of algorithm std::unique.
I've read in http://en.cppreference.com/w/cpp/container/list/unique that within 'unique' predicate we shouldn't change objects, so is it safe by the term of standard to delete the “going to be removed” objects in list::unique?
And if so, what object in list::unique should be considered as a duplicate? In gnu implementation the 'b' will be removed, but in http://www.cplusplus.com/reference/list/list/unique/ is written that in pred(i, i-1), i item will be removed, so does this behaviour specified by standard ?
Is this (working in gcc) code correct in term of standard or is UB?
List.sort( [] (const Val *a, const Val *b) {
return *a < *b;
});
List.unique([] (const Val *a, const Val *b) {
if (*a == *b) {
delete b; // (1) working in gcc 4.6
// or (2) delete a (elsewhere)?
return true;
}
return false;
}) ;
Update #1
Mike's explanation was the most helpful one, but for now we're using such solution:
struct RawPtrEq {
bool operator()(const Val a, const Val b) { return *a == *b;}
};
auto it = adjacent_find( begin(List), end(List), RawPtrEq() );
while(it != end(li)) {
delete *it;
it = List.erase(it);
it = adjacent_find( it, end(List), RawPtrEq() );
}
No, there's no guarantee that this is well defined. unique is not specified completely enough to guarantee that this is the last time that b is passed to the predicate, so it's possible that the deleted pointer might be used again later.
I'm surprised that it works for you, since the specification is for b to be the first of the two elements, which is the one that would be kept if the either were removed.
I'd suggest storing either the objects themselves, or unique_ptr<Val> if you really need them to be dynamic, so that they are always destroyed automatically on removal. I've no idea why you say "we can't use smart pointers"; they would make much more sense than jumping through hoops to leave your legacy code unchanged.
I have this:
map<string,int> a;
int b;
And i'd like to make this:
switch(b)
{
case a["someStr1"]:
someCode1();
break;
case a["someStr2"]:
someCode2();
break;
etc.
}
But it doesn't compiles. How to implement this correctly?
switch conditions need to be constants, so what you want to do here is not possible.
You're better off using some if statements.
switch/case are meant for constants (e.g., enum, ints etc.).
You can use the map<>::iterator to run through the values and compare with b.
for(map<string,int>::const_iterator it = a.begin(), end = a.end(); it != end; it++)
{
if(it->second == b)
{
...
break;
}
}
This way you can avoid the code duplication for comparison, if your a is large enough.
Also, you can explore the option of replacing for loop with for_each.
You can't.
Expression after case in a switch statement must be integral compile-time constant. So a literal (42), const int variable initialized with a literal (const int x = 66 ... case x:) or enum value. And thats about it.
The reason this is so strict is efficiency. Compilers usually create labels for each case and if you know the value for each label at compile time, you can make some nice optimizations that avoid most of the overhead a normal code branching has.
In your case just go with if-else:
if(b == a["someStr1"]) {
//...
} else if(b == a["someStr2"]) {
//...
} // and so on