I receive an array as a pointer from a function and want to initialize a QVector from that.
For now I do it like this:
void foo(double* receivedArray, size_t size)
{
QVector<double> vec(size);
std::copy(receivedArray, receivedArray + size, std::begin(vec));
}
Would it be equally possible to do this:
void foo(double* receivedArray, size_t size)
{
QVector<double> vec(size);
vec.data() = receivedArray;
}
Would this break some kind of Qt mechanism that I am not aware of?
The first one does unnecessary work, initializing the vector with default-constructed doubles before filling it. Unfortunately, QVector lacks a ranged-insertion, so you must resort to algorithms:
void foo(double* receivedArray, size_t size)
{
QVector<double> vec;
vec.reserve(size); // warning: size_t->int cast
std::copy(receivedArray, receivedArray + size, std::back_inserter(vec));
}
The second version does not even compile, as data() returns a T *, which is a rvalue that you can't put on the left side of an assignment.
QVector::data does not return a reference to the underlying pointer, so you cannot assign to vec.data() (it is not an lvalue, it will not even compile):
template <typename T>
struct Vector {
T* data_;
T* nref_data () { return data_; }
T* &ref_data () { return data_; }
};
Vector<int> vec;
vec.ref_data() = new int[100]; // Ok, Vector<int>::ref_data returns a reference
vec.nref_data() = new int[100]; // Nok, Vector<int>::nref_data does not return a reference
Another solution:
void foo(double* receivedArray, size_t size)
{
QVector<double> vec(receivedArray,receivedArray+size);
}
see also:
http://cpp.sh/7jfi6
Related
for an embedded system we need a custom vector class, where the capacity is set during compile-time through a template parameter.
Until now we had an array of objects as a member variable.
template<class T, size_t SIZE>
class Vector {
...
T data[SIZE];
}
The problem here of course is that if T isn't a POD, the default constructors of T are called. Is there any way to let data be uninitialized until a corresponding push() call (with placement new inside)? Just using
uint8_t data[SIZE * sizeof(T)];
possibly breaks the alignment of T. We absolutely cannot use dynamic memory, the total container size always needs to be known at compile-time. We also cannot use C++'s alignas specifier since the compiler does not support C++11 yet :(
First I would check if the compiler has support for alignment, ie gcc has __attribute__(aligned(x)), there is likely something similar.
Then if you absolutely have to have aligned uninitialized data without such support, you will have to waste some space
// Align must be power of 2
template<size_t Len, size_t Align>
class aligned_memory
{
public:
aligned_memory()
: data((void*)(((std::uintptr_t)mem + Align - 1) & -Align)) {}
void* get() const {return data;}
private:
char mem[Len + Align - 1];
void* data;
};
And you'd use placement new with it
template<typename T, size_t N>
class Array
{
public:
Array() : sz(0) {}
void push_back(const T& t)
{
new ((T*)data.get() + sz++) T(t);
}
private:
aligned_memory<N * sizeof(T), /* alignment */> data;
size_t sz;
};
Live
The alignment of T can be found with C++11 alignof, check your compiler to see if it supports anything that can be used to find out its alignment. You can also just take a guess from printed pointer values and hope that's enough.
Another way is to use std::vector<> with a custom allocator that allocates on the stack.
This way you would create an empty vector, reserve the required space, which should be equal to the space your allocator allocates for you on the stack, and then populate the vector using vector<>::emplace_back. Your element type can be non-copyable but must be movable in this case.
E.g.:
#include <vector>
struct X {
X(int, int);
// Non-copyable.
X(X const&) = delete;
X& operator=(X const&) = delete;
// But movable.
X(X&&);
X& operator=(X&&);
};
template<class T, std::size_t N>
struct MyStackAllocator; // Implement me.
int main() {
std::vector<X, MyStackAllocator<X, 10>> v;
v.reserve(10);
v.emplace_back(1, 2);
v.emplace_back(3, 4);
}
Information about how to implement an allocator is widely available, for example, search YouTube for "c++ allocator".
You are going to have to use placement new along with a union trick to get the alignment properly set.
// use `std::max_align_t` and `std::aligned_storage` when you have it
// since don't have access to alignof(), use the presumably max
// alignment value
using MaxAlign = long;
template <typename T, int size>
class UninitializedArray {
union Node {
char data[sizeof(T)];
MaxAlign alignment;
};
Node aligned_data[size];
bool initialized;
public:
UninitializedArray() : initialized(false) {}
void initialize() {
for (int i = 0; i < static_cast<int>(size); ++i) {
new (&this->aligned_data[i].data) T();
}
this->initialized = true;
}
~UninitializedArray() {
if (this->initialized) {
for (int i = 0; i < static_cast<int>(size); ++i) {
T* ptr = reinterpret_cast<T*>(&this->aligned_data[i].data);
ptr->~T();
}
}
}
T& operator[](int index) {
if (!this->initialized) {
this->initialize();
}
T* ptr = reinterpret_cast<T*>(&this->aligned_data[i].data);
return *ptr;
}
};
And then use it like this
UninitializedArray<Something, 5> arr;
arr[0].do_something();
If you ever get C++17 working, then you can use std::array and std::optional to make this easy
std::optional<std::array<T, N>> optional_array;
// construct the optional, this will construct all your elements
optional_array.emplace();
// then use the value in the optional by "treating" the optional like
// a pointer
optional_array->at(0); // returns the 0th object
Using C++, I am trying to create an array that holds pointers to objects I'm storing. But when the array is full, I want to expand the array.
the easy option is to allocate a new array with bigger size, then copy the elements to it, this is quite inefficient, and I thought of another way I want to try to do it:
create array of fixed size X
When full, create a new array, and make the end of the first array point to the start of the first element
Repeat as long as needed
What methods can I use to do that? I thought of one way to do it, but it seems very hacky:
declare all my new array as pointers to object pointer, then reinterprit_cast the filled elements to object pointer.
Note: I know I can use Vector, but I am instructed not to use std library.
Kind Regards,
There are some good answers in the comments already. I just want to provide a way to achieve exactly the behavior you described.
Since the elements of the array are pointers as well, you can define a union as the element of your array like this:
template<typename T>
union Cell
{
T* pElm;
Cell* pNext;//A fixed size array of Cells
}
And then build your array on top of it. For example:
template<typename T>
class SpecialArray
{
public:
//the next pointer is included
static const size_t ARRAY_LEN = 1000;// For example
using Pointer = T*;
using Segment = Cell<T>[ARRAY_LEN];
protected:
Segment* pFirst;
size_t mSize;
public:
SpecialArray()
:pFirst(nullptr),mSize(0){}
SpecialArray(SpecialArray&&){}
~SpecialArray(){}
Pointer& operator[](size_t index)
{
Segment* seg = pFirst;
size_t offest = 0;
//Search logic...
return seg[offest]->pElm;
}
const Pointer& operator[](size_t index) const;
};
Using C++, I am trying to create an array that holds pointers to
objects I'm storing. But when the array is full, I want to expand the
array.
With C++ templates and C primitives we can improvise a simple vector like below. And the grow buffer strategy is to double the size when the threshold is met.
#include <iostream>
#include <stdlib.h>
template <typename T>
class MyVector
{
public:
MyVector() : m_count(0), m_size(0), m_buffer(0)
{
m_size = bufInitSize;
m_buffer = (T*)malloc(sizeof(T) * bufInitSize);
}
~MyVector()
{
if (m_buffer)
free(m_buffer);
}
void add(const T& p)
{
if (m_count + 1 >= m_size)
{
m_size *= 2;
m_buffer = (T*)realloc(m_buffer, sizeof(T) * m_size);
}
m_buffer[m_count ++ ] = p;
}
T& operator[](int idx)
{
return m_buffer[idx];
}
private:
static const int bufInitSize = 1024;
T* m_buffer;
int m_count;
int m_size;
};
void main()
{
// using MyVector
MyVector<int*> vctOfIntPtr;
int n = 100;
vctOfIntPtr.add(&n);
int* pN = vctOfIntPtr[0];
std::cout << *pN;
}
im pretty new in c++ and my problem is the following:
i need an array in which i want so save values. all valus are of the same type.
there are two cases: the array should save int values or float.
when i compile, i dont knwo yet which type it will be, so it has to be defined while executing the programm.
i tried something like this:
void* myArray;
int a = 10;
if(something){
myArray = new int[a];
}
else{
myArray = new float[a];
}
after this i want so calculate things with these values, but i always get errors because the array is still void
There are several ways of doing this in C++:
You could use a void* and add reinterpret_cast<...> as needed,
You could make an array of unions that have both an int and a float, or
You could use templates.
The first two approaches are idiomatic to C, but not to C++. Both approaches are workable, but they result in solutions that are hard to understand and maintain.
The third approach lets you do things very cleanly:
template <typename T>
void calc() {
// You could use std::vector<T> here for even better flexibility
T* a = new T[10];
... // Perform your computations here
delete[] a;
// You don't need a delete if you use std::vector<T>
}
int main() {
...
// You can make a type decision at runtime
if (mustUseInt) {
calc<int>();
} else {
calc<float>();
}
return 0;
}
struct calculator : public boost::static_visitor<> {
void operator()(const std::vector<int>& vi) const {
// evaluate the array as ints
}
void operator()(const std::vector<float>& vf) const {
// evaluate the array as floats
}
};
using nasty_array = boost::variant<std::vector<int>, std::vector<float>>;
std::unique_ptr<nasty_array> myArray;
int a = 10;
if (something) {
myArray.reset(std::vector<int>(a));
}
else {
myArray.reset(std::vector<float>(a));
}
boost::apply_visitor( calculator(), *myArray );
I use a C library which operates on 2D arrays in the form of Foo**. I use it inside C++ code, so I need some sort of wrapper. With 1D arrays it's straightforward because vector iterators are just pointers, but in case of 2D it gets more complicated. Is it possible to make a wrapper for Foo** without copying the data?
The elements of a vector<Foo> are stored in a dynamically allocated contiguous memory, so you can get a pointer Foo* to the array, as you do in your first case.
But the elements of a nested vector vector<vector<Foo> > are not stored as a contiguous 2D array, so you can't get a Foo** directly.
You could try something like this :
vector<vector<Foo> > data;
vector<Foo*> data_rows;
for(auto it = data.begin(); it != data.end(); ++it) {
//in c++11, you can use data() instead of casting begin()
data_rows.push_back(it->data());
}
Foo** c_data = data_rows.data();
That way you're not copying the data, just the row pointers.
I would propose to build a class overriding operator [], which holds the C pointer Foo** internally.
E.g.:
template <class T>
class Mat<T> {
private: T** ptr; int n; int m; //< 2D array is of size n x m
public: Mat( int n, int m ) : n(n), m(m) {}
Col<T> operator[]( int k ) { assert(k<n); return Col<T>(*(ptr+k*n)); }
T& get(int k, int i ) { return *(*(ptr+k*n)+i); }
}
having defined
template <class T>
class Col<T> { private: T* ptr;
public: T& operator[]( int i ) { return *(ptr+i); }
Col<T>(T* ptr) : ptr(ptr) { }
}
The code may not be 100% correct, but i hope you get the point and can reimplement it.
Also make sure livetime of pointerdata exceeds your c++ wrapper (also wrap the refcount mechanism of the c library?).
The nice point of operator[] is, that now you can use it like that:
Foo** ptr = from_some_c_library();
Mat<Foo> mat(ptr,3,4);
Foo& element_at_2_2 = mat[2][2];
assert( mat.get(2,2) == mat[2][2] );
Note that you may want to implement custom iterators for Mat<T> to make it work with STL functions.
How do I define a typedef for a fixed length array so that I can also 'new'. The following does not work:
typedef double Vector[3];
Vector *v = new Vector; // does not compile
We are trying to wrap into C++ some old C code which handles float * and float (*)[3] in a generic way.
The pointer to an double[3] is double * - so this will work:
typedef double Vector[3];
double *v = new Vector;
But I suggest you don't use it that way - to delete the array you need the array-delete-operator:
delete[] v;
But on new Vector you don't see it is an array and so it might be forgotten.
This case is handled (and strongly recommended to avoid) in Scott Meyers Effective C++. So better don't use an typedef here.
class Vector
{
public: // methods
double * data() { return mData; }
const double * data() const { return mData; }
double & operator[](int i) { return mData[i]; }
double operator[](int i) const { return mData[i]; }
private: // attributes
double mData[3];
};
will allow
Vector * pv = new Vector;
Vector & v = *pv;
v[0] = 1;
v[1] = 2;
v[2] = 3;
pass_it_to_legacy_lib(v.data());
delete pv;
One issue with your original example is that it would invoke the new operator where the new[] would actually be correct. Also, it would make it non-obvious that delete[] had to be used instead of plain delete.
The class approach doesn't need new[] and takes full advantage of the apriori fixed length.
If you're happy to use templates in your C++ code, something like this could work..
template <typename T, int S>
struct array
{
array() : _inst() {}
template<typename _F>
void operator()(_F & f)
{
f(_inst);
}
operator T*() { return _inst; }
// real array
T _inst[S];
};
typedef array<double, 4> d4;
void foo(double*)
{
}
int main(void)
{
d4 d; // no need for new, but you can use if you want
// first way to call is to pass the function to the array object, which will then
// visit
d(foo);
// take advantage of the type operator (operator T*)
foo(d);
}
#include <cassert>
#include <vector>
using namespace std;
template<typename Type, int Dimension>
const vector<Type> make_fixed_vector(const Type& value = Type())
{
return vector<Type>(Dimension, value);
}
int main(void)
{
vector<int> v3 = make_fixed_vector<int, 3>();
assert(v3.size() == 3);
}
C++1x compilers are able to deduce the type of a variable, which is handy when declaring multi-dimensional "fixed" vectors using this technique:
.
.
.
template<typename Type, int Rows, int Columns>
const vector<vector<Type> > make_fixed_vector_vector(const Type& value = Type())
{
return vector<vector<Type> >(Rows, make_fixed_vector<Type, Columns>(value));
}
int main(void)
{
auto vv = make_fixed_vector_vector<int, 3, 4>(42);
assert(vv.size() == 3);
assert(vv[0].size() == 4);
assert(vv[0][0] == 42);
assert(vv[2][3] == 42);
}
I had this simple idea when programming a parser-function for list expressions which shall return a fixed-size vector of vector of integers. For example, a vector<vector<int> >(1) for a expression like "(0,8)", but a vector<vector<int> >(2) for a expression like "(3-4)(5)" and so on. In the application up to 5 parenthesized definitions are possible, which represent logical references to program data. I first try to parse a vector<vector<int> >(5). Worked? Ok, got reference type A, the most detailed one. Otherwise vector<vector<int> >(4) indicates a reference type B etc.
For this purpose make_fixed_vector worked well, but from a general perspective the technique has flaws. Most notably, since make_fixed_vector returns no true type, its dimension(s) cannot be checked at compile-time. At runtime reserve, resize and push_back calls are possible. And, since function templates cannot have default template arguments, custom allocators require more typing:
template<typename Type, int Dimension, template<typename> class Allocator>
const vector<Type Allocator<Type> > make_fixed_vector(const Type& value = Type())
{
return vector<Type, Allocator<Type> >(Dimension, value);
}
vector<int> v3 = make_fixed_vector<int, 3, std::allocator>();
etc. etc. But this technique keeps smaller projects basic. Unless this virtue is relevant Boost's boost::array might be more realistic.