I have an unique pointer on a dynamically allocated array like this:
const int quantity = 6;
unique_ptr<int[]> numbers(new int[quantity]);
This should be correct so far (I think, the [] in the template parameter is important, right?).
By the way: Is it possible to initialize the elements like in int some_array[quantity] = {}; here?
Now I was trying to iterate over the array like this:
for (auto it = begin(numbers); it != end(numbers); ++it)
cout << *it << endl;
But I cannot figure out, how the syntax is right. Is there a way?
Alternatively I can use the index like:
for (int i = 0; i < quantity; ++i)
cout << numbers[i] << endl;
Is one of these to be preferred?
(Not directly related to the title: As a next step I would like to reduce that to a range-based for loop but I just have VS2010 right now and cannot try that. But would there be something I have to take care of?)
Thank you! Gerrit
Compiler is supposed to apply this prototype for std::begin:
template< class T, size_t N >
T* begin( T (&array)[N] );
It means the parameter type is int(&)[N], neither std::unique_ptr nor int *. If this is possible, how could std::end to calculate the last one?
But why not use raw pointer directly or a STL container?
const int quantity = 6;
std::unique_ptr<int[]> numbers{new int[quantity]};
// assignment
std::copy_n(numbers.get(), quantity,
std::ostream_iterator<int>(std::cout, "\n"));
const int quantity = 6;
std::vector<int> numbers(quantity, 0);
// assignment
std::copy(cbegin(numbers), cend(numbers),
std::ostream_iterator<int>(std::cout, "\n"));
Dynamically allocated arrays in C++ (ie: the result of new []) do not have sizing information. Therefore, you can't get the size of the array.
You could implement std::begin like this:
namespace std
{
template<typename T> T* begin(const std::unique_ptr<T[]> ptr) {return ptr.get();}
}
But there's no way to implement end.
Have you considered using std::vector? With move support, it shouldn't be any more expensive than a unique_ptr to an array.
Related
I need to create a vector or similar list of pairs, where the first element of a pair is of class T, and the second element is a pointer to the next pair.
Illustration
template<class T>
std::vector<std::pair<T, T*>> createPointingVector(std::vector<T> vec) {
std::vector<std::pair<T, T*>> new_vec;
for (int i=0; i<vec.size(); i++){
new_vec.push_back(std::make_pair(vec[i], &(vec[i - 1])));
}
return new_vec;
}
I understand that std::vector<std::pair<T, T*>> is incorrect because the second element of the pair is not supposed to be of type *T but rather a recursive *std::pair<T, *std::pair<T, *std::pair<T, ...>>>.
Is it possible to fix my code or what are the other ways to achieve my goal, if any?
I strongly recommend rethinking using a bare vector.
My reason for that is that you need to guarantee that that the memory of the vector is never reallocated. Note that you also should in any case make sure that your vector is made sure to allocate all required memory from the start, either by initializing with empty elements or by using std::vector::reserve.
Otherwise, if you have a pointer already set and then change the capacity of the vector, the pointer becomes invalid, a good setup if you want undefined behaviour.
Therefore I strongly advise you to use a wrapper class around your vector, which makes sure no capacity change is ever called.
Now, if you do that, the thing is, why do you use actual pointers?
Consider using data of type std::vector<std::pair<T, size_t> >, with the second entry actually storing the position within the vector, rather than an actual pointer:
template<class T>
class PointingVector
{
public:
PointingVector(const std::vector<T>& vec);
private:
std::vector<std::pair<T, size_t> > data;
};
template<class T>
PointingVector<T>::PointingVector(const std::vector<T>& vec)
{
for (int i=0; i<vec.size()-1; i++)
{
data.push_back(std::make_pair(vec[i], i+1));
}
data.push_back(std::make_pair(vec.back(), 0)); // assuming that the last points to the first
}
After that, make sure that every additional method you add leaves the pointing consistent. Like should you write something similar to erase, make sure that all pairs are updated accordingly.
And the analogy to dereferencing is trivial:
template<class T>
std::pair<T, size_t>& PointingVector<T>::get(size_t index)
{
return data[index];
}
The important thing about my solution is that you can exclude possible bugs in regard to dangling pointers. Those are really bad, especially since they might not cause an error in test executions, given the nature of undefined behaviour. Worst thing in my solution is that the indices are wrong after calling a method that has a bug.
And if you want to introduce anything that changes the capacity of the vector, no problem, no need to redo any pointers. Just make sure the indices are changed accordingly. If you did this with pointers, your first step would probably be to create a list of indices anyway, so why not work with one directly.
Plus, as this solution has no (visible) pointers at all, you don't need to do any memory management.
Another solution: Ditch std::pair and define your own type:
template<class T>
struct Node
{
T data;
Node* next; // or a smart pointer type
Node(const T& data, Node* next) : data(data), next(next) {}
};
Then build up your vector like this:
template<class T>
std::vector<Node<T>*> createPointingVector(const std::vector<T>& vec)
{
std::vector<Node<T>*> new_vec;
for (int i=0; i<vec.size(); i++)
{
new_vec.push_back(new Node<T>(vec[i], nullptr));
}
for (int i=0; i<vec.size()-1; i++)
{
new_vec[i]->next = new_vec[i+1];
}
new_vec[vec.size()-1]->next = new_vec[0];
return new_vec;
}
Note that without smart pointers, you need to do memory management. I'd consider making next a weak_ptr<Node>, and have the vector be over shared_ptr<Node>. That way, the memory is automatically deallocated as soon as the vector gets deleted (assuming you have no other pointers active).
What you ask is doable, but according to the illustration found linked within your answer, the pointers should point one-up circularly inside the input vector, and not one-down, as is in your code example. What I mean is:
new_vec[0] = {vec[0], &vec[1]}
new_vec[1] = {vec[1], &vec[2]}
...
new_vec[N-1] = {vec[N-1], &vec[0]}
above, N = vec.size().
I attach a minimum working example:
#include <iostream>
#include <vector>
#include <utility> // std::pair, std::make_pair
template<class T>
std::vector<std::pair<T, T*> > createPointingVector(std::vector<T>& vec) { // important: make the parameter a reference
std::vector<std::pair<T, T*> > new_vec;
int vec_size = vec.size();
for (int i = 0; i < vec_size-1; i++)
new_vec.push_back( std::make_pair( vec[i], &(vec[i + 1]) ) ); // pointers assigned according to linked picture
new_vec.push_back( std::make_pair( vec[vec_size-1], &vec[0] ) );
return new_vec;
}
int main()
{
std::vector<int> input = {1,2,3,4};
std::vector<std::pair<int,int*> > sol = createPointingVector(input);
for (auto i : sol)
std::cout << i.first << " -> " << *(i.second) << std::endl;
return 0;
}
I have a method to shuffle arrays, but it's not working and I don't know how to fix it now. How can I create a new array in main from the array returned by shuffleArray as I can't assign the shuffled array to a new array and it's giving me the same index for the elements?
using namespace std;
template <class T> T min (T array, T size){
int min=array[0];
for(int i=1;i<size;i++){
if(array[i]<min){min=array[i];}
}
return min;
}
template <class T> T indexOf (T array[], const int size, T value){
for(int i=0;i<size;i++){
if(array[i]==value){return value;}
}
return -1;
}
template <class T> T shuffleArray (T array[], T size){
T* Array2 = new T[size];
for(int i=0;i<size;i++){
Array2[i]=array[i];
}
random_shuffle(&Array2[0],&Array2[size]);
return *Array2;
}
int main(){
int a[]= {1,2,3,4,5};
int index = indexOf(a, 5, 3);
cout << endl << "The index is:" << shuffleArray(a, 5)<<endl;
cout << endl << "The index is:" << index<<endl;
return 0;
}
Short Answer: Use std container as std::array, they have appropriate copy constructors and save you some headache. By the way std::array is also not slower as a raw array (it is basically the raw array, but wrapped in a class and given some nice member functions to work with it).
Detailed Answer: I am not entirely sure, what you like to print to std::cout. But most likely it should be the position of 3 before and after shuffling. Then the code should look like this (to compile with std=c++11 for use of constexpr and auto):
#include <iostream>
#include <algorithm> // std::min, std::find and std::random_shuffle
#include <array> // use std::array instead of raw pointers
// using namespace std; Bad idea, as tadman points out in comment
// use std::min instead of
// template <class T> T min (T array, T size)
// use std::find instead of
// template <class T> T indexOf (T array[], const int size, T value){
// T is not the value_type of the array, but the array iteself. Works also for all other std containers with random access iterators
template<class T> T shuffleArray(T array) // array is copied here
{
// shuffle
std::random_shuffle(array.begin(), array.end());
// return copy of array
return array;
}
int main()
{
constexpr int numberToFind = 3; // constexpr is not necessary, but the variable seems not intented to change in this code
// use standard container instead of raw array
std::array<int,5> a = {1,2,3,4,5};
// iterator to numberToFind in a
auto it = std::find(a.begin(), a.end(), numberToFind); // auto deduces the type, so you do not have to write std::array<int,t>::iterator and by the way the code is more flexible for changes
// shuffle a and store result in aShuffled
auto aShuffled = shuffleArray(a);
// iterator to numberToFind in aShuffled
auto itShuffled = std::find(aShuffled.begin(), aShuffled.end(), numberToFind);
// pointer arithmetics give the index
std::cout << "The index before shuffling is:" << it - a.begin() << std::endl;
std::cout << "The index after shuffling is:" << itShuffled - aShuffled.begin() << std::endl;
return 0;
}
As some comments already tell you, a few tips for the future:
Use std containers instead of raw pointers of raw arrays
Use well tested algorithms from the standard library instead of writing your own, unless you have very specific needs
auto makes live very easy in C++11 to handle also the iterator types. By the way you have to change almost nothing to use std::vector instead of std::array. The first declaration is enough.
Always when you use a new there has to be a delete. Otherwise you create a memory leak. Again this can be generally avoided by using the standard container.
Use descriptive names instead of literals. This makes your code more clear and readable.
I'm trying to create a class which maintains a fixed size vector of unique pointers to managed objects, like so:
std::vector<std::unique_ptr<Myclass>> myVector;
The vector gets initialized like so:
myVector.resize(MAX_OBJECTS,nullptr);
Now, what I need to to, is to be able to, on request, remove one of the stored unique pointers without affecting the size of the vector.
I also need to safely add elements to the vector too, without using push_back or emplace_back.
Thanks in advance.
Edit: I want the vector to be of constant size because I want to be able to add and remove elements in constant time.
If you want a vector of fixed size, use std::array.
To remove a unique_ptr in an index, you can use std::unique_ptr::reset():
myVector[i].reset()
To add an element to a specific index (overwriting what was there before) you can use std::unique_ptr::reset() with the new pointer as parameter:
myVector[i].reset(new Myptr(myparameter));
Reading a reference may also help:
http://en.cppreference.com/w/cpp/memory/unique_ptr
http://en.cppreference.com/w/cpp/container/array
http://en.cppreference.com/w/cpp/container/vector
Looks like you want to use a std::array<> rather than forcing std::vector<> to behave like one.
As already pointed out you should use std::array if the size is fixed.
E.g like this:
std::array<std::unique_ptr<YourType>, MAX_OBJECTS> myVector;
You can then remove or add a new pointer like this.
for(auto& v : myVector)
if(v && predicate)
v.reset();// or v.reset(ptr) to set a new one
You can use STL algorithm std::remove, like this:
// all items that should be removed will be the range between removeAt and end(myVector)
auto removeAt = std::remove_if(begin(myVector), end(myVector),
ShouldRemovePredicate);
// reset all items that should be removed to be nullptr
for(auto it = removeAt; it != end(myVector); ++it)
it->reset();
In addition, if the size is known at compile-time I would suggest using std::array<unique_ptr<MyObject>, SIZE> instead of a vector. However, if SIZE is not known at compile-time your code is ok.
You could use std::array instead of a std::vector since you know the number of the elements beforehand and you could add and remove elements like the following example:
#include <iostream>
#include <memory>
#include <array>
class foo {
std::size_t id;
public:
foo() : id(0) {}
foo(std::size_t const _id) : id(_id) {}
std::size_t getid() const { return id; }
};
auto main() ->int {
// construct an array of 3 positions with `nullptr`s
std::array<std::unique_ptr<foo>, 3> arr;
// fill positions
std::unique_ptr<foo> p1(new foo(1));
arr[0] = std::move(p1);
std::unique_ptr<foo> p2(new foo(2));
arr[1] = std::move(p2);
std::unique_ptr<foo> p3(new foo(3));
arr[2] = std::move(p3);
// print array
for(auto &i : arr) if(i != nullptr) std::cout << i->getid() << " ";
std::cout << std::endl;
// reset first position (i.e., remove element at position 0)
arr[0].reset();
// print array
for(auto &i : arr) if(i != nullptr) std::cout << i->getid() << " ";
std::cout << std::endl;
return 0;
}
LIVE DEMO
I have the following array:
int* myArray = new int[45];
If I wanted to iterate each element without knowing the actual size of the array, I would need to use a for_each?
If so, then how would you write the for_each? I was looking over the following site and reading up on for_each but can't figure out how to put this together.
http://www.cplusplus.com/reference/algorithm/for_each/
Update: A for_each is not a good choice in this case, due to the fact that the size of the array has to be known. vectors are the proper way to accomplish such task. My reason for using arrays, in this case, was for learning purposes. if this was a serious project I would move to something such as Lists/Vectors.
Note when the question was first posted, the array in question was declared as
int myArray[45];
This answer deals with that particular case.
If you have C++11 support, you can use a range based loop:
for (int& i : myArray) {
std::cout << i << "\n";
}
C++11 also provides std::begin and std::end, which you can use with a fixed size array to obtain iterators:
std::for_each(std::begin(myArray), std::end(myArray), <func>);
Another option, which works for C++03 and you are dealing with fixed size arrays, is to define a function template:
// taken a fixed size array by reference and loop over it
template <typename T, unsigned int N>
void array_for_each( T (&a)[N]) {
for (unsigned int i = 0; i < N; ++i) {
// do something with array elements
std::cout << a[i] << " ";
}
}
int main() {
int a[5];
array_for_each(a);
}
If you use MSVC (Microsoft Visual C++), you can use "for each."
for each(int i in arr) {
cout << i << ' ' << endl;
}
NOTE: This only works in the block of code the array is declared in.
If not, you can also use the new range-based for loop in the C++11 standard.
for(int i : arr) {
cout << i << ' ' << endl;
}
If you're intent upon the std::for_each:
for_each(arr,arr + 10,[] (int i) {
cout << i << ' ' << endl;
});
NOTE: This requires knowledge of the size of the array (in this example, 10).
You could use a for_each. In this case, you have allocated space for 45 elements in your array, but since it is NULL, you'd probably get a segfault if you tried to do anything. You either need to hold a value of the array, or use something like sizeof(myArray)/sizeof(myArray[0]) (which has its own problems).
Anyway, for a for_each here, if we actually had 45 elements:
std::for_each(myArray, myArray + 45, <func>);
Anyway, this is part of the reason to use vectors: .begin() and .end() reduces errors with using incorrect indexing.
You have described an array of int, not a class that implements a InputIterator, which is what the for_each is designed for, even though you can use it to iterate an array, but you need to know the size of the array to iterate it.
If you want to use for_each you need to use a vector, list, or implement a class that keeps track of the number of elements it contains. IMO it is much easier to just use a vector
If you want to just iterate your current array, assuming it is 0 terminated:
for(int *value = myArray; *value != 0; ++value)
printf("%d\n", *value);
Or, you can use indexes:
for(int index = 0; myArray[index] != 0; ++index)
printf("%d\n", myArray[index]);
IMO the pointer method is cleaner.
This code is still dangerous though, you should either keep track of the number of records in a seperate variable, or use a vector.
Is this undefined behavior?
std::array<int, 5> x = {3, 5, 1, 2, 3};
std::array<int, 3>& y = *reinterpret_cast<std::array<int, 3>*>(&x[1]);
for(int i = 0; i != 3; i++) {
std::cout << y[i] << "\n";
}
Maybe yes, but I really feel like there should be a safe way to slice std::arrays.
EDIT: Following Radek's suggestion:
template<unsigned N, unsigned start, unsigned end, typename T>
std::array<T, end - start>& array_slice(std::array<T, N>& x)
{
static_assert(start <= end, "start <= end");
static_assert(end <= N-1, "end <= N");
return *reinterpret_cast<std::array<T, end - start>*>(&x[start]);
}
EDIT: Ok, I decided that I'm unhappy with std::arrays and will move to something else, any ideas?
Yes, that is undefined behavior. You're taking one type and reinterpret_casting it to another. Indeed, the use of the reinterpret_cast should be a big red flag for "here there be dragons!"
As for slicing arrays, that's not going to happen. A std::array contains values; a slice of this would contain references to part of that array. And therefore, it would not be a std::array. You can copy slices of arrays, but not using std::array. You would need to use std::vector, since it allows the calling of constructors, as well as construction from a range of values. Remember: std::array is just a nicer wrapper around a C-style array.
The committee is looking into a template array_ref<T> class, which is exactly what it says: a reference to some segment of an array of type T. This could be a regular C-style array, a std::vector, a std::array, or just some memory allocated with new T[]. There are some library implementations of the class already, but nothing is standardized yet.
Following Radek's suggestion:
Hiding the undefined behavior in a function does not make it defined behavior. You can try to pretend that it isn't undefined, but it still is. The moment you use that reinterpret_cast, you willingly give up living in C++-land.
What about a placement new?
#include <array>
#include <iostream>
#include <iterator>
template<typename T, std::size_t N>
struct array_slice : public std::array<T,N> {
~array_slice() = delete;
};
int main() {
std::array<double,4> x_mu{0.,3.14,-1.,1.};
std:: cout << &x_mu << std::endl;
{
auto slicer = [] (std::array<double,4>& ref) {
array_slice<double,3>* p = new (&ref) array_slice<double,3>;
return p;
};
std::array<double,3>& x_ = *slicer(x_mu);
std::copy(x_.begin(),x_.end(),
std::ostream_iterator<float>(std::cout," "));
std:: cout << std::endl;
std:: cout << &x_ << std::endl;
}
std::copy(x_mu.begin(),x_mu.end(),
std::ostream_iterator<float>(std::cout," "));
}