Reputation: 27
I want to pass an array into an instance of a class to be used within it. However, I can't get sizeof() the array. I get the warning "Sizeof on array function parameter will return size of 'float *' instead of 'float []'. "
int main() {
float info[]={1.0f,2.3f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,67.8f};
Store test(info);
test.showArrayContents();
{
Class I want to pass array to
class Store{
float array[];
public:
Store(float temp[]){
std::cout<<"\n"<<sizeof(temp); //can't get sizeof
for(int i=0;i<9;i++){
array[i]=temp[i];
};
}
void showArrayContents(){
for(int i=0;i<9;i++){
std::cout<<array[i];
}
}
};
How can I fix to get sizeof() correctly?
EDIT: I'm not trying to find how many elements are in the array but the amount of memory it takes up, which should be 40 bytes.
Upvotes: 1
Views: 510
Reputation: 7539
For a static C-style array it is possible to infer its size using the expression
sizeof(info) / sizeof(*info)
This is also commonly implemented via a macro ARRAY_SIZE
. Beware however that in the above code there is no check that the actual array is a static one.
Conversely, for a dynamically allocated C-style array, there is no possibility to infer its size, since the variable itself is nothing but a pointer.
In the class constructor, even if you knew the size of the array (for instance by passing the size as parameter), or if you assume that only a static array is used (and you employ the code above to infer its size), your code has a serious bug here:
for(int i=0;i<9;i++){
array[i]=temp[i];
};
You are copying the elements of temp
into array
, but did you reserve memory for that? Again, array
is merely a pointer to float
, and if you do not explicitly allocate memory, in the above code you are writing into a part of memory which does not pertain to array
. Hence you have UB.
If you know at compile time the size of the array, the right type to use is std::array
.
For instance
std::array<float, 10> info = {1.0f,2.3f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,67.8f};
And then you can pass it to the class with something like
class Store{
std::array<float, 10> array;
public:
Store(std::array<float, 10> temp) : array{temp} { }
...
With a std::array
you can always know its size with std::array::size.
Upvotes: 2
Reputation: 12759
I want to pass an array into an instance of a class to be used within it.
Ok, there are several ways to do that, I'll show you some of those later.
However, I can't get
sizeof()
the array.
You can't get it inside the function, after the array decayed to a pointer.
Store(float temp[]){
// ^^^^^^ This is a pointer to float, not an array
}
Other than explicitly passing the size as a function argument, you could pass a reference to an array, using a template parameter to store the size (1).
#include <vector>
#include <iostream>
class Store
{
std::vector<float> values_;
public:
template< std::size_t N >
Store(float const (&temp)[N]) : values_{temp, temp + N}
{}// ^^^^^^^^^^
void showArrayContents() const noexcept
{
for(auto i : values_)
{
std::cout << ' ' << i;
}
std::cout << '\n';
}
};
int main()
{
float info[]={1.0f,2.3f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,67.8f};
Store test(info);
test.showArrayContents();
}
Get rid of the source array and use a std::initializer_list
(2).
#include <vector>
#include <iostream>
#include <initializer_list>
class Store
{
std::vector<float> values_;
public:
Store(std::initializer_list<float> src) : values_{src}
{}
//...
};
int main()
{
Store test{1.0f,2.3f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,67.8f};
test.showArrayContents();
}
If the size never has to change during the lifetime of Store
, you can use a std::array
(3).
#include <algorithm>
#include <array>
#include <iostream>
template< class T, std::size_t N >
class Store
{
std::array<T, N> values_;
public:
Store(T const (&src)[N])
{
std::copy(src, src + N, values_.begin());
}
//...
};
//deduction guide
template<class T, std::size_t N> Store( T (&src)[N] ) -> Store<T, N>;
int main()
{
float info[]={1.0f,2.3f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,67.8f};
Store test(info);
test.showArrayContents();
}
You can also avoid the source array and initialize the class with a constructor accepting a template parameter pack (4).
#include <algorithm>
#include <array>
#include <iostream>
#include <type_traits>
template< class T, std::size_t N >
class Store
{
std::array<T, N> values_;
public:
template< class... Args >
Store(Args... args) : values_{args...}
{}
//...
};
//deduction guide
template< class... Args >
Store(Args &&... ) -> Store<std::common_type_t<Args...>, sizeof...(Args)>;
int main()
{
Store test{1.0f,2.3f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,67.8f};
test.showArrayContents();
}
Upvotes: 3
Reputation: 5321
How can I fix to get sizeof() correctly?
Option #1: you could pass in the size of the array.
#include <array>
#include <cstddef>
#include <iostream>
using std::cout;
using std::size;
using std::size_t;
namespace {
class Store {
size_t array_size;
float* array;
public:
~Store() {
delete[] array;
}
Store(float temp[], size_t temp_size) : array_size{temp_size} {
cout << "temp_size:" << temp_size << "\n";
array = new float[temp_size];
for (size_t i = 0; i < temp_size; ++i) {
array[i] = temp[i];
}
}
Store(Store const&) = delete;
auto operator=(Store const&) -> Store& = delete;
void showArrayContents() {
auto sep = "";
for (size_t i = 0; i < array_size; ++i) {
cout << sep << array[i];
sep = " ";
}
cout << "\n";
}
};
} // anon
int main() {
float info[] = { 1.0f, 2.3f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 67.8f };
Store test(info, size(info));
test.showArrayContents();
}
Option #2: you could use a template constructor for the array.
#include <cstddef>
#include <iostream>
using std::cout;
using std::size_t;
namespace {
class Store {
size_t array_size;
float* array;
public:
~Store() {
delete[] array;
}
template <size_t N>
Store(float (&temp)[N]) : array_size{N} {
cout << "N:" << N << "\n";
array = new float[N];
for (size_t i = 0; i < N; ++i) {
array[i] = temp[i];
}
}
Store(Store const&) = delete;
auto operator=(Store const&) -> Store& = delete;
void showArrayContents() {
auto sep = "";
for (size_t i = 0; i < array_size; ++i) {
cout << sep << array[i];
sep = " ";
}
cout << "\n";
}
};
} // anon
int main() {
float info[] = { 1.0f, 2.3f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 67.8f };
Store test(info);
test.showArrayContents();
}
Option #3 (best option): you could use std::vector
.
#include <cstddef>
#include <iostream>
#include <vector>
#include <utility>
using std::cout;
using std::move;
using std::ostream;
using std::size_t;
using std::vector;
namespace {
class Store {
vector<float> array;
public:
Store(vector<float> temp) : array{move(temp)} {
cout << "temp size:" << temp.size() << "\n";
}
void showArrayContents(ostream& out) const {
auto sep = "";
for (auto&& e : array) {
out << sep << e;
sep = " ";
}
out << "\n";
}
};
} // anon
int main() {
auto info = vector<float>{ 1.0f, 2.3f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 67.8f };
auto test = Store{info};
test.showArrayContents(cout);
}
Upvotes: 1
Reputation: 820
You should pass the array length as an argument also, when you pass an array to function what you actually pass is a pointer to start location of array i.e. float*
in your case, so when you ask for size it simply gives you size of pointer .
So either pass the size explicitly, or use std::vector
which will give you the length.
other than that if class Store
is the owner of array, why not define it inside class?
Upvotes: 0