Passing reference to deque delete function - c++

I have been given an assignment and I'm struggling to figure out how I'm supposed to implement it.
I've pasted the parts of the assignment that puzzled me below
Write a deque class to hold a list of integers which is implemented internally with a circular array The size of the array can be passed in the constructor, or you can decide on a default value. The class will maintain data members which hold the index position of the head and tail of the list
The class should have member functions:
• bool isEmpty();
• bool isFull();
• bool insertFront(int)
• bool removeFront(int&)
• bool insertBack(int)
• bool removeBack(int&)
prints all items in the array by removing them one at a time from the front.
So I've written all my function and have the deque working, the things I struggled with are:
"The size of the array can be passed in the constructor"
so to accomplish this I declared a pointer called array in my class and then array = new int[size] in my constructor, is this the only way to do this, I'm happy enough it works but not sure if there's a better solution. I was thinking vector, but think that would have been too easy. I also could have declared a const for the size and initialized the array in my class, but again to easy.
The bool removeFront(int&) and bool removeBack(int&) functions really confused me, what reference am I supposed to be passing in? also the return type is bool, but later in the assignment I'm asked to "prints all items in the array by removing them one at a time from the front" how can I do this with a return type of bool, rather than int?
I have changed my functions to remove the reference and have a return type of int to get the code to work, but would like to know how to implement it the way the assignment asks for?

Based on the requirements listed, the intent of the function arguments is unambiguous. Here is why:
Take
bool removeFront(int& );
This not only removes an element at the front of the buffer and stores it in the argument being passed by reference. But, the function returns a "bool" indicating whether it was able to successfully remove or not.
An example usage would be like this:
int elem;
while (removeFront(elem)) {
printf("element : %d ", elem);
}
Here the variable "elem" is passed in by reference. Hence, upon a successful execution of removeFront() you will have elem filled in with the value of the element just removed.
The same reasoning applies to other similar methods. Please go back to using a reference mode parameter as given in the original specification.
The int& argument is not for a count of elements as other answer suggested.
Answer to Part-1:
Your solution is pretty decent. You could also
std::array for storing the elements. There is an advanced trick to do in-place allocation of a variable length array - but, that is beyond the scope of this question.

"The size of the array can be passed in the constructor"
Unless you were told otherwise, use a vector. Using old school arrays is just asking for trouble.
The "bool removeFront(int&)" and "bool removeBack(int&)" functions really confused me, what reference am I supposed to be passing in?
It's a matter of personal preference, but passing in a single int as a reference might be rather unnecessary, what the functions do (if I understood your problem correctly) is remove the element of the array that is at the position of the int you are passing as argument. If said element is correctly removed, you might want to return a true value, otherwise return a false one.
EDIT: Upon re reading the post, what the functions might do is simply remove the 'int' amount of elements from the front or back of the array. Return values should work as previously stated
but later in the assignment I'm asked to "prints all items in the array by removing them one at a time from the front" how can I do this with a return type of bool, rather than int?
The return type of the function has nothing to do with this (unless you were asked to do it recursively). Simply do a loop that starts at the beginning of the array and outputs its content, deletes that same element, then jumps to the next and repeats the process until its out of elements. Again, this is much safer to do with any of the STL containers since you can use iterators.

Related

C++ unordered_map/map [] operator default initialization value [duplicate]

I have a std::map like this:
map<wstring,int> Scores;
It stores names of players and scores. When someone gets a score I would simply do:
Scores[wstrPlayerName]++;
When there is no element in the map with the key wstrPlayerName it will create one, but does it initialize to zero or null before the increment or is it left undefined?
Should I test if the element exists every time before increment?
I just wondered because I thought primitive-type things are always undefined when created.
If I write something like:
int i;
i++;
The compiler warns me that i is undefined and when I run the program it is usually not zero.
operator[] looks like this:
Value& map<Key, Value>::operator[](const Key& key);
If you call it with a key that's not yet in the map, it will default-construct a new instance of Value, put it in the map under key you passed in, and return a reference to it. In this case, you've got:
map<wstring,int> Scores;
Scores[wstrPlayerName]++;
Value here is int, and ints are default-constructed as 0, as if you initialized them with int(). Other primitive types are initialized similarly (e.g., double(), long(), bool(), etc.).
In the end, your code puts a new pair (wstrPlayerName, 0) in the map, then returns a reference to the int, which you then increment. So, there's no need to test if the element exists yet if you want things to start from 0.
This will default-construct a new instance of value. For integers, the default construction is 0, so this works as intended.
You should not test if the item exists before incrementing it. The [] operator does exactly what you need it to do, as others have said.
But what if the default-constructed value wouldn't work for you? In your case the best way to find if the element already exists is to try to insert it. The insert member function for std::map returns a std::pair<iterator, bool>. Whether the insert succeeds or fails, the first element of the pair will point to the desired object (either your new one, or the one that was already present). You can then alter its value as you see fit.
Check rules for initialization.
See section 4.9.5 Initialization of C++ Prog Lang or C++ std book. Depending on whether your variable is local, static, user-defined or const default initialization can happen.
In you case, int is called POD (Plain old Datatype). Any auto (created on heap / local variable) POD variable is not default initialized. Hence for you "i" above will not have value zero.
Always make an habit of initializing POD when defined in heap. You can even use int() to initialize value.

Is it costly to pass an initializer_list as a list by value?

I want to pass a std::list as a parameter to fn(std::list<int>), so I do fn({10, 21, 30}) and everybody is happy.
However, I've come to learn that one shouldn't pass list by value, cause it's costly. So, I redefine my fn as fn(std::list<int> &). Now, when I do the call fn({10, 21, 30}), I get an error: candidate function not viable: cannot convert initializer list argument to 'std::list<int> &'.
QUESTION TIME
Is the "you shall not pass an costly object by value" rule valid here? We aren't passing a list after all, but an initializer_list, no?
If the rule still applies, what's the easy fix here?
I guess my doubt comes from the fact that I don't know clearly what happens when one passes an initializer_list argument to a function that accepts a list.
Is list generated on the spot and then passed by value? If not, what is it that actually happens?
However, I've come to learn that one shouldn't pass list by value, cause it's costly.
That's not entirely accurate. If you need to pass in a list that the function can modify, where the modifications shouldn't be externally visible, you do want to pass a list by value. This gives the caller the ability to choose whether to copy or move from an existing list, so gives you the most reasonable flexibility.
If the modifications should be externally visible, you should prevent temporary list objects from being passed in, since passing in a temporary list object would prevent the caller from being able to see the changes made to the list. The flexibility to silently pass in temporary objects is the flexibility to shoot yourself in the foot. Don't make it too flexible.
If you need to pass in a list that the function will not modify, then const std::list<T> & is the type to use. This allows either lvalues or rvalues to be passed in. Since there won't be any update to the list, there is no need for the caller to see any update to the list, and there is no problem passing in temporary list objects. This again gives the caller the most reasonable flexibility.
Is the "you shall not pass an costly object by value" rule valid here? We aren't passing a list after all, but an initializer_list, no?
You're constructing a std::list from an initializer list. You're not copying that std::list object, but you are copying the list items from the initializer list to the std::list. If the copying of the list items is cheap, you don't need to worry about it. If the copying of the list items is expensive, then it should be up to the caller to construct the list in some other way, it still doesn't need to be something to worry about inside your function.
If the rule still applies, what's the easy fix here?
Both passing std::list by value or by const & allow the caller to avoid pointless copies. Which of those you should use depends on the results you want to achieve, as explained above.
Is list generated on the spot and then passed by value? If not, what is it that actually happens?
Passing the list by value constructs a new std::list object in the location of the function parameter, using the function argument to specify how to construct it. This may or may not involve a copy or a move of an existing std::list object, depending on what the caller specifies as the function argument.
The expression {10, 21, 30} will construct a initializer_list<int>
This in turn will be used to create a list<int>
That list will be a temporary and a temporarys will not bind to a
non-const reference.
One fix would be to change the prototype for you function to
fn(const std::list<int>&)
This means that you can't edit it inside the function, and you probably don't need to.
However, if you must edit the parameter inside the function, taking it by value would be appropriate.
Also note, don't optimize prematurely, you should always use idiomatic
constructs that clearly represents what you want do do, and for functions,
that almost always means parameters by const& and return by value.
This is easy to use right, hard to use wrong, and almost always fast enough.
Optimization should only be done after profiling, and only for the parts of the program that you have measured to need it.
Quoting the C++14 standard draft, (emphasis are mine)
18.9 Initializer lists [support.initlist]
2: An object of type initializer_list provides access to an array of
objects of type const E. [ Note: A pair of pointers or a pointer plus
a length would be obvious representations for initializer_list.
initializer_list is used to implement initializer lists as specified
in 8.5.4. Copying an initializer list does not copy the underlying
elements. —end note ]
std::list has a constructor which is used to construct from std::initializer_list. As you can see, it takes it by value.
list(initializer_list<T>, const Allocator& = Allocator());
If you are never going to modify your parameter, then fn(const std::list<int>&) will do just fine. Otherwise, fn(std::list<int>) will suffice well for.
To answer your questions:
Is the "you shall not pass an costly object by value" rule valid here?
We aren't passing a list after all, but an initializer_list, no?
std::initializer_list is not a costly object. But std::list<int> surely sounds like a costly object
If the rule still applies, what's the easy fix here?
Again, it's not costly
Is list generated on the spot and then passed by value? If not, what is it that actually happens?
Yes, it is... your list object is created on the spot at run-time right before the program enters your function scope
However, I've come to learn that one shouldn't pass list by value, cause it's costly. So, I redefine my fn as fn(std::list &). Now, when I do the call fn({10, 21, 30}), I get an error: candidate function not viable: cannot convert initializer list argument to 'std::list &'.
A way to fix the problem would be:
fn(std::list<int>& v) {
cout << v.size();
}
fn(std::list<int>&& v) {
fn(v);
}
Now fn({1, 2, 3 }); works as well (it will call the second overloaded function that accepts a list by rvalue ref, and then fn(v); calls the first one that accepts lvalue references.
fn(std::list<int> v)
{
}
The problem with this function is that it can be called like:
list<int> biglist;
fn(biglist);
And it will make a copy. And it will be slow. That's why you want to avoid it.
I would give you the following solutions:
Overloaded your fn function to accept both rvalues and lvalues
properly as shown before.
Only use the second function (the one that accepts only rvalue
references). The problem with this approach is that will throw a compile error even if it's called with a lvalue reference, which is something you want to allow.
Like the other answers and comments you can use a const reference to the list.
void fn(const std::list<int>& l)
{
for (auto it = l.begin(); it != l.end(); ++it)
{
*it; //do something
}
}
If this fn function is heavily used and you are worried about the overhead of constructing and destructing the temporary list object, you can create a second function that receives the initializer_list directly that doesn't involve any copying whatsoever. Using a profiler to catch such a performance hot spot is not trivial in many cases.
void fn(const std::initializer_list<int>& l)
{
for (auto it = l.begin(); it != l.end(); ++it)
{
*it; //do something
}
}
You can have std::list<> because in fact you're making temporary list and passing initializer_list by value is cheap. Also accessing that list later can be faster than a reference because you avoid dereferencing.
You could hack it by having const& std::list as parameter or like that
void foo( std::list<int> &list ) {}
int main() {
std::list<int> list{1,2,3};
foo( list );
}
List is created on function scope and this constructor is called
list (initializer_list<value_type> il,
const allocator_type& alloc = allocator_type())
So there's no passing list by value. But if you'll use that function and pass list as parameter it'll be passed by value.

Pass vectors by pointer and reference in C++

A quick question about how to safely pass and use vectors in c++.
I know that when using vectors you have to be very careful with addresses to them and their elements because when you dynamically change their size they may change their address (unless you use reserve etc. but I'm imagining I will not know how much space I will need).
Now I want to pass an existing vector (created elsewhere) to a function which adapts it and changes it size etc. but I'm a little unclear as to what is safe to do because I would normally achieve all of this with pointers. On top of this there is using references to the vector and this just muddies the water for me.
For instance take the two following functions and comments in them
void function1(std::vector<int>* vec){
std::cout<<"the size of the vector is: "<<vec->size()<<std::endl; //presumably valid here
for (int i=0;i<10;i++){
(*vec).pushback(i); //Is this safe? Or will this fail?
// Or: vec->pushback(i); Any difference?
}
std::cout<<"the size of the vector is: "<<vec->size()<<std::endl; //Is this line valid here??
}
AND
void function2(std::vector<int>& vec){
std::cout<<"the size of the vector is: "<<vec.size()<<std::endl; //presumably valid here
for (int i=0;i<10;i++){
vec.pushback(i); //Is this safe? Or will this fail?
}
std::cout<<"the size of the vector is: "<<vec.size()<<std::endl; //Is this line valid here??
}
Is there any difference between the two functions, both in terms of functionality and in terms of safety?
Or in other words, if I only have a pointer/reference to a vector and need to resize it how can I be sure where the vector will actually be in memory, or what the pointer to the vector really is, after I operate on it. Thanks.
In term of functionality, in the very limited context you gave us, they are essentially the same.
In more general view, if you want to write generic code, consider that operation and operators bind directly to reference, but not to pointers
a = b + c;
To compile requires
A operator+(const B&, const C&);
But
A* operator+(const B*, const C*);
is all a different beast.
Also, an expression taking reference and taking value have the same syntax, but an expression taking pointers require pointers to be deference to provide equal semantics, but this leads to different expression syntax ( *a + *b against a+b ) thus leading to "less general code".
On the counterpart, if you are writing a class that have runtime polymorphism (and lyskov substitution in mind), you will most likely treat dynamically allocated object, and hence, manipulating them through pointers may be more natural.
There are "grey areas" where the two things mesh, but -in general- pointer taking function are more frequent in runtime based OOP frameworks, while reference taking functions are more frequent in "value based generic algorithms", where static type deduction is expected, and on-stack based allocation is most likely wanted.

Is there a reason for zero sized std::array in C++11?

Consider the following piece of code, which is perfectly acceptable by a C++11 compiler:
#include <array>
#include <iostream>
auto main() -> int {
std::array<double, 0> A;
for(auto i : A) std::cout << i << std::endl;
return 0;
}
According to the standard § 23.3.2.8 [Zero sized arrays]:
1 Array shall provide support for the special case N == 0.
2 In the case that N == 0, begin() == end() == unique value. The return value of
data() is unspecified.
3 The effect of calling front() or back() for a zero-sized array is undefined.
4 Member function swap() shall have a noexcept-specification which is equivalent to
noexcept(true).
As displayed above, zero sized std::arrays are perfectly allowable in C++11, in contrast with zero sized arrays (e.g., int A[0];) where they are explicitly forbidden, yet they are allowed by some compilers (e.g., GCC) in the cost of undefined behaviour.
Considering this "contradiction", I have the following questions:
Why the C++ committee decided to allow zero sized std::arrays?
Are there any valuable uses?
If you have a generic function it is bad if that function randomly breaks for special parameters. For example, lets say you could have a template function that takes N random elements form a vector:
template<typename T, size_t N>
std::array<T, N> choose(const std::vector<T> &v) {
...
}
Nothing is gained if this causes undefined behavior or compiler errors if N for some reason turns out to be zero.
For raw arrays a reason behind the restriction is that you don't want types with sizeof T == 0, this leads to strange effects in combination with pointer arithmetic. An array with zero elements would have size zero, if you don't add any special rules for it.
But std::array<> is a class, and classes always have size > 0. So you don't run into those problems with std::array<>, and a consistent interface without an arbitrary restriction of the template parameter is preferable.
One use that I can think of is the return of zero length arrays is possible and has functionality to be checked specifically.
For example see the documentation on the std::array function empty(). It has the following return value:
true if the array size is 0, false otherwise.
http://www.cplusplus.com/reference/array/array/empty/
I think the ability to return and check for 0 length arrays is in line with the standard for other implementations of stl types, for eg. Vectors and maps and is therefore useful.
As with other container classes, it is useful to be able to have an object that represents an array of things, and to have it possible for that array to be or become empty. If that were not possible, then one would need to create another object, or a managing class, to represent that state in a legal way. Having that ability already contained in all container classes, is very helpful. In using it, one then just needs to be in the habit of relating to the array as a container that might be empty, and checking the size or index before referring to a member of it in cases where it might not point to anything.
There are actually quite a few cases where you want to be able to do this. It's present in a lot of other languages too. For example Java actually has Collections.emptyList() which returns a list which is not only size zero but cannot be expanded or resized or modified.
An example usage might be if you had a class representing a bus and a list of passengers within that class. The list might be lazy initialized, only created when passengers board. If someone calls getPassengers() though then an empty list can be returned rather than creating a new list each time just to report empty.
Returning null would also work for the internal efficiency of the class - but would then make life a lot more complicated for everyone using the class since whenever you call getPassengers() you would need to null check the result. Instead if you get an empty list back then so long as your code doesn't make assumptions that the list is not empty you don't need any special code to handle it being null.

Using stable_sort() to sort doubles as ints

I have a huge array of ints that I need to sort. The catch here is that each entry in the list has a number of other associated elements in it that need to follow that int around as it gets sorted. I've kind of solved this problem by changing the sorting to sort doubles instead of ints. I've tagged each number before it was sorted with a fractional part denoting that value's original location before the sort, thus allowing me to reference it's associated data and allowing me to efficiently rebuild the sorted list with all the associated elements.
My problem is that I want to sort the double values by ints using the function stable_sort().
I'm referring to this web page: http://www.cplusplus.com/reference/algorithm/stable_sort/
However, since I'm a new programmer, i don't quite understand how they managed to get the sort by ints to work. What exactly am i supposed to put into that third argument to make the function work? (i know i can just copy and paste it and make it work, but i want to learn and understand this too).
Thanks,
-Faken
Edit: Please note that I'm a new programmer who has had no formal programming training. I'm learning as i go so please keep your explanations as simple and as rudimentary as possible.
In short, please treat me as if i have never seen c++ code before.
Since you say you're not familiar with vectors (you really should learn STL containers ASAP, though), I assume you're playing with arrays. Something along these lines:
int a[] = { 3, 1, 2 };
std::stable_sort(&a[0], &a[3]);
The third optional argument f of stable_sort is a function object - that is, anything which can be called like a function by following it with parentheses - f(a, b). A function (or rather a pointer to one) is a function object; other kinds include classes with overloaded operator(), but for your purposes a plain function would probably do.
Now you have your data type with int field on which you want to sort, and some additional data:
struct foo {
int n;
// data
...
};
foo a[] = { ... };
To sort this (or anything, really), stable_sort needs to have some way of comparing any two elements to see which one is greater. By default it simply uses operator < to compare; if the element type supports it directly, that is. Obviously, int does; it is also possible to overload operator< for your struct, and it will be picked up as well, but you asked about a different approach.
This is what the third argument is for - when it is provided, stable_sort calls it every time it needs to make a comparison, passing two elements as the arguments to the call. The called function (or function object, in general) must return true if first argument is less than second for the purpose of sorting, or false if it is greater or equal - in other words, it must work like operator < itself does (except that you define the way you want things to be compared). For foo, you just want to compare n, and leave the rest alone. So:
bool compare_foo_n(const foo& l, const foo& r) {
return l.n < r.n;
}
And now you use it by passing the pointer to this function (represented simply by its name) to stable_sort:
std::stable_sort(&a[0], &a[3], compare_foo_n);
You need to pass the comparison function. Something like this:
bool intCompare(double first, double second)
{
return static_cast<int>(first) < static_cast<int>(second);
}
int main()
{
std::vector<double> v;
v.push_back(1.4);
v.push_back(1.3);
v.push_back(2.1);
v.push_back(1.5);
std::stable_sort(v.begin(), v.end(), intCompare);
return 0;
}
Inside the sort algorithm, to compare the values the comparison function passed by you is used. If you have a more complex data structure and want to sort on a particular attribute of the data structure then you can use this user-defined function to compare the values.
I believe you are talking about this function:
bool compare_as_ints (double i,double j)
{
return (int(i)<int(j));
}
And the function call:
stable_sort (myvector.begin(), myvector.end(), compare_as_ints);
The function compare_as_ints is a normal function but this is being passed to the stable_sort as a function pointer. i.e., the address of the function is being passed which would be used by stable_sort internally to compare the values.
Look at this function pointer tutorial if you are unclear about this.