What is the difference between these two declarations?
int myints[5];
array<int,5> myints;
If I use the first declarations and the function size(), there will be a error "Member reference base type 'int [5]' is not a structure or union".
But if I use the second declarations and the function size(), the program works.
Why would the first declarations does not work?
#include <iostream>
#include <iomanip>
#include <array>
using namespace std;
int main()
{
//int myints[5]; //illegal
array<int,5> myints; //legal
cout << "size of myints: " << myints.size() << endl; //Error if I use the first declarations
cout << "sizeof(myints): " << sizeof(myints) << endl;
}
As others have pointed out, std::array is an extension added
to C++11 (so you may not have it), which wraps a C style array,
in order to give it some (but not all) of an STL-like interface.
The goal was that it could be used everywhere a C style array
could; in particular, it accepts the same initialization syntax
as C style arrays, and if the initialization type allows static
initialization, its initialization can be static as well. (On
the other hand, the compiler cannot deduce its size from the
length of the initializer list, which it can for the older
C style arrays.)
With regards to size, any experienced programmer will have
a size function in their toolkit, along the same lines as
std::begin and std::end (which are C++11 extensions, and
which everyone had in their toolkit before C++11 standardized
them). Something like:
template <typename T>
size_t
size( T const& c )
{
return c.size();
}
template <typename T, size_t n>
size_t
size( T (&a)[n] )
{
return n;
}
(In modern C++, the second could even be constexpr.)
Given this, you write size( myInts ), regardless of whether it
is an std::array or a C style array.
array<int,5> myints uses an std::array, a template that overlays enhanced functionality on-top of a "basic" C/C++ array (which is what int myints[5] is). With a basic array, you are just reserving a chunk of storage space, and are responsible for keeping track of its size yourself (although you can use sizeof() to help with this).
With the std::array you get helper functions that can make the array safer and easier to use.
std::array is new in C++11. As you have found, it has a size function. This tells you how many items are in the array.
sizeof on the other hand tells you how much memory a variable is taking up i.e. its size in bytes.
array is a template class that has size() as it's member function while int[] is simple C array
By using int myints[5]; , you are declaring an array of 5 ints on the stack, which is the basic C array.
Instead, by using array<int,5> myints; you are declaring an object of type array, which is a container class defined by the STL (http://en.cppreference.com/w/cpp/container/array), which in turns implements the size()function to retrieve the container's size.
The STL containers are built on top of the "basic" C types to provide extra functionality and to make it easier to manage them.
int myints[5]; has no function size() but you can do
int size = sizeof(myints)/ sizeof(int);
to get the size of the array.
so basically you can do:
#include <iostream>
#include <iomanip>
#include <array>
using namespace std;
int main()
{
int myintsArr[5]; //legal
array<int,5> myints; //legal
cout << "size of myints: " << myints.size() << endl; //Error if I use the first declarations
cout << "sizeof(myintsArr): " << sizeof(myintsArr)/ sizeof(int) << endl;
}
and get the same result from both the arrays
Related
I'm trying to create an array and the size of the array depends on the user input. But there is an error in my code, It said: "expression must have a constant value".
Here is my code:
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
int var;
cout << "What size do you want to choose: "<< endl;
cin >> var;
int arr[var];
}
How can I change my code and make it work?
How can I change my code and make it work?
Change
int arr[var];
to
std::vector<int> arr(var);
This will require #include <vector>
The syntax you are using is known as a "variable length array", and is NON-STANDARD. Only a few compilers support it as an vendor-specific extension to the C++ language.
A standard compliant fixed-length array must have its size known to the compiler as a compile-time constant.
For what you want, you need to use the new[] operator instead:
int *arr = new int[var];
...
delete[] arr;
Or better, use a std::vector container:
#include <vector>
std::vector<int> arr(var);
To allocate an array dynamically, we use the array form of new and delete (often called new[] and delete[]):
#include <iostream>
int main()
{
std::cout << "Enter a positive integer: ";
int length{};
std::cin >> length;
int *array{ new int[length]{} }; // use array new. Note that length does not need to be constant!
std::cout << "I just allocated an array of integers of length " << length << '\n';
array[0] = 5; // set element 0 to value 5
delete[] array; // use array delete to deallocate array
// we don't need to set array to nullptr/0 here because it's going to go out of scope immediately after this anyway
return 0;
}
Arrays in C++ must have constant size known at compile-time. You can preallocate several constant sizes known at compile time and offer the user to choose one of them. Alternatively, you can use another data structure that allows dynamic size allocation e.g std::vector.
Good luck!
Could someone explain to me why the offsetof function does not work on std::vectors as shown below:
#include <windows.h>
#include <iostream>
#include <vector>
using namespace std;
struct FooStruct {
double x;
double y[10];
std::vector<double> z;
};
int main() {
cout << offsetof(FooStruct, x) << endl;
cout << offsetof(FooStruct, y[2]) << endl;
cout << offsetof(FooStruct, z[2]) << endl;
system("Pause");
}
Calling offsetof(FooStruct, z[2]) produces the following compiling error:
cannot apply 'offsetof' when 'operator[]' is overloaded
offsetof(FooStruct, z[2]) makes no sense. The elements of z are not contained within a FooStruct, they're accessed via the std::vector, which has at its core a pointer to some other allocation on the heap within which z[2] can be found.
In any case, the error (which seems confusing I understand) is probably popping up because std::vector overloads operator[], not because your class FooStruct overloads operator[] (which, assuming we see the whole definition, it doesn't).
If you want to find the offset of z[2] in relation to z[0], you could just compute the difference between &z[0] and &z[2] like this: std::cout << (&z[2] - &z[0]) << '\n';
Because offsetof isn't a function but a macro, and only works on POD types, or standard layout class in C++11. It's only there for backward compatibility with C.
The reason the compiler refuses to allow you to use the subscription operator, all issues aside, is because the macro is evaluated at compile time, but the overloaded operator might do some work at runtime to calculate the result.
I am a total C++ noob, and I am having some trouble returning an array from my methods. I have a header file with the following method declaration:
virtual double[]
echoDoubleArray(double[] doubleArray, int arraySize) throw (RemoteException);
This gives me the following error:
../common/EchoService.h: At global scope:
../common/EchoService.h:25: error: expected unqualified-id before ‘[’ token
What is the correct way to return an array?
C++ doesn't play nice with non-local arrays, more likely you should be using an actual container like std::array<double,10> or std::vector<double>. I don't think it's possible to return an array from a function.
You'll better use std::vector or if you really want to return a plain array, return a pointer (to such an array) dynamically allocated with e.g.
double* arr = new double[arrSize];
// fill arr appropriately
return arr;
But I'll recommend returning a std::vector<double> instead.
Sorry everyone seems to be telling you to use modern STL type programming instead of answering your question. They are right. But you should still understand how things work. The problem with returning arrays are that arrays created in your function will be on the stack. When you leave your function they will not exist anymore. What you can do is return a pointer to an array on the Heap. Research a little more about the stack and the heap to understand. But below is a simple C++ function returning an array allocated on the Heap.
#include <iostream>
double * MakeArray()
{
double *mydouble = new double[5];
mydouble[1]=1.1;
mydouble[1]=2.2;
return mydouble;
}
int main()
{
double *d=MakeArray();
std::cout<<d[1]<<d[2];
delete[] d;
}
edit:
Thinking about it some more, another way to do it without STL would be returning a struct with an array in it. Most compilers will return a struct by value (assuming your not doing embedded programming).
Probably the best simple way: Pass your array into the function. It is like passing a reference because you are really just passing a pointer.
#include <iostream>
void MakeArray(double d[5])
{
d[0] = 0.0; d[1] = 1.1;
d[2] = 2.2; d[3] = 3.3; d[4] =4.4;
}
int main()
{
double dub[5];
MakeArray(dub);
std::cout<<dub[1]<<dub[2];
}
After understanding how everything works. go use the STL.
There is a technique for passing arrays that do not decay to pointers. You pass the array by reference, using the syntax below. The required "extra" parens are a syntactical wart, and probably why this usage is not more common. One gets used to it real fast, given the advantages.
void sub(double (&foo)[4])
{
cout << sizeof(foo) << endl;
}
Prints 32, not sizeof(double*), because the type of foo really is a reference to an array of 4 doubles. Using templates, you can generalize to work for any size of array:
template <int N> sub(double (&foo)[N])
{
cout << sizeof(foo) << endl;
}
double bar[5];
double zot[3];
sub(bar); // ==> 40
sub(zot); // ==> 24
You can generalize again to handle an any-size array of anything:
template <class T, int N>void sub(T(&foo)[N])
{
cout << sizeof(foo) << endl;
}
double bar[5];
char zot[3];
sub(bar); // ==> 40
sub(zot); // ==> 3
and you now have something that captures the abstract idea of "sub" regardless of the type or size of the array you pass it.
The C++ syntax for arrays is: std::vector<double> instead of double[]. It also requires you to put #include <vector> near the top of your source file. Other than that they work very similar to C-arrays.
To answer your question more directly, if you declare an array of doubles as follows:
double doubleArray[] = {1.0, 2.0, 3.0};
you would declare the method like this:
virtual double *
echoDoubleArray(double* doubleArray, int arraySize) throw (RemoteException);
Arrays are passed as pointers. If you want to use the true power of C++, then follow the advice provided in the other answers.
Here is a simplified version of what I have (not working):
prog.h:
...
const string c_strExample1 = "ex1";
const string c_strExample2 = "ex2";
const string c_astrExamples[] = {c_strExample1, c_strExample2};
...
prog.cpp:
...
int main()
{
int nLength = c_astrExamples.length();
for (int i = 0; i < nLength; i++)
cout << c_astrExamples[i] << "\n";
return 0;
}
...
When I try to build, I get the following error:
error C2228: left of '.length' must have class/struct/union
The error occurs only when I try to use member functions of the c_astrExamples.
If I replace "c_astrExamples.length()" with the number 2, everything appears to work correctly.
I am able to use the member functions of c_strExample1 and c_strExample2, so I think the behavior arises out of some difference between my use of strings vs arrays of strings.
Is my initialization in prog.h wrong? Do I need something special in prog.cpp?
Arrays in C++ don't have member functions. You should use a collection like vector<string> if you want an object, or compute the length like this:
int nLength = sizeof(c_astrExamples)/sizeof(c_astrExamples[0]);
Just use STL vector of strings instead of array:
#include <string>
#include <vector>
using namespace std;
const string c_strExample1 = "ex1";
const string c_strExample2 = "ex2";
vector<string> c_astrExamples;
c_astrExamples.push_back(c_strExample1);
c_astrExamples.push_back(c_strExample2);
int main()
{
int nLength = c_astrExamples.size();
Arrays in C++ are inherited from C, which wasn't object-oriented. So they aren't objects and don't have member functions. (In that they behave like int, float and the other built-in types.) From that ancestry stem more problems with array, like the fact that they easily (e.g., when passed into a function) decay into a pointer to the first element with no size information left.
The usual advice is to use std::vector instead, which is a dynamically resizable array. However, if you the array size is known at compile-time and you need a constant, then boost's array type (boost::array, if your compiler supports the TR1 standard extensions also available as std::tr1::array, to become std::array in the next version of the C++ standard) is what you want.
Edit 1:
A safe way to get the length of an array in C++ involves an incredible combination of templates, function pointers and even a macro thrown into the mix:
template <typename T, std::size_t N>
char (&array_size_helper(T (&)[N]))[N];
#define ARRAY_SIZE(Array_) (sizeof( array_size_helper(Array_) ))
If you (like me) think this is hilarious, look at boost::array.
Edit 2:
As dribeas said in a comment, if you don't need a compile-time constant, this
template <typename T, std::size_t N>
inline std::size_t array_size(T(&)[N])
{return N;}
is sufficient (and much easier to read and understand).
c_astrExamples is an array, there is no "length()" method in it.
In C++ arrays are not objects and have no methods on it. If you need to get the length of the array you could use the following macro
#define COUNTOF( array ) ( sizeof( array )/sizeof( array[0] ) )
int nLength = COUNTOF(c_astrExamples);
Also, beware of initialisation in a header file. You risk offending the linker.
You should have:
prog.h:
extern const string c_strExample1;
extern const string c_strExample2;
extern const string c_astrExamples[];
I'm trying to simply print out the values contained in an array.
I have an array of strings called 'result'. I don't know exactly how big it is because it was automatically generated.
From what I've read, you can determine the size of an array by doing this:
sizeof(result)/sizeof(result[0])
Is this correct? Because for my program, sizeof(result) = 16 and sizeof(result[0]) = 16 so that code would tell me that my array is of size 1.
However that doesn't appear correct, because if I manually print out the array values like this:
std::cout << result[0] << "\n";
std::cout << result[1] << "\n";
std::cout << result[2] << "\n";
std::cout << result[3] << "\n";
etc...
...then I see the resulting values I'm looking for. The array is upwards of 100+ values in length/size.
It seems like it should be very simple to determine the size/length of an array... so hopefully I'm just missing something here.
I'm a bit of a C++ newb so any help would be appreciated.
You cannot determine the size of an array dynamically in C++. You must pass the size around as a parameter.
As a side note, using a Standard Library container (e.g., vector) allieviates this.
In your sizeof example, sizeof(result) is asking for the size of a pointer (to presumably a std::string). This is because the actual array type "decays" to a pointer-to-element type when passed to a function (even if the function is declared to take an array type). The sizeof(result[0]) returns the size of the first element in your array, which coincidentally is also 16 bytes. It appears that pointers are 16 bytes (128-bit) on your platform.
Remember that sizeof is always evaluated at compile-time in C++, never at run-time.
As a side comment, there are better ways of checking the size of an array (for the cases where the array is in scope and has not decayed into a pointer) that are typesafe:
// simple: runtime result
template <typename T, std::size_t N>
inline std::size_t sizeof_array( T (&)[N] ) {
return N;
}
// complex: compile time constant
template <typename T, std::size_t N>
char (&static_sizeof_array( T(&)[N] ))[N]; // declared, not defined
#defined SIZEOF_ARRAY( x ) sizeof(static_sizeof_array(x))
In both cases the compiler will detect if you try to pass in a pointer (dynamic array or decayed array):
void f( int array[] ) { // really: void f( int *array )
{
// sizeof_array(array); // compile time error
// int another[SIZEOF_ARRAY(array)]; // compile time error
}
int main() {
int array[] = { 1, 2, 3 };
std::cout << sizeof_array(array) << std::endl; // prints 3
int another_array[ SIZEOF_ARRAY(array) ];
std::cout << sizeof_array(another_array) << std::endl; // 3 again
}
If what you have is a "real" array, then the sizeof(x)/sizeof(x[0]) trick works. If, however, what you have is really a pointer (e.g. something returned from a function) then that trick doesn't work -- you'll end up dividing the size of a pointer by the sizeof a pointer. They are pointers to different types, but on a typical system all pointers are the same size, so you'll get one. Even when the pointers are different sizes, the result still won't have anything to do with how many strings you have.
Better use std::vector<std::string> instead of a raw array. Then you don't have to manually manage the arrays memory and you can use the size() method if you want to know the number of elements.
If you use a dynamically allocated raw array you are expected to keep track of its size yourself, the size cannot be obtained from the array. Best save it in an extra variable.
The sizeof(array)/sizeof(element) works for fixed-length-array of fixed-length-arrays (not of pointers).
As an array of strings we most often use a (fixed-length-)array of pointers-to-various-(fixed-)length-strings so this trick wouldn't work.
sizeof() is used for objects which size is known at compile time. It's not applicable to dynamically allocated data itself.
When an object contains pointers like in the case of an array of strings,
sizeof() returns the size of the highest-level (fixed-size) structure. Often it's just the size of a single pointer. It does not include the size of the allocated data pointed to by the pointers. Because that data actually is not part of the main object, it's indeed one or more separate objects (we have aggregation here instead of composition, see http://en.wikipedia.org/wiki/Object_composition).
In C++ using vectors is very convenient for your needs. Other suitable standard containers could be used too.
length() and size() methods are synonyms, see http://www.cplusplus.com/reference/string/string/size/)
P.S. Please note that for std::string s object sizeof(s) is a constant independent of the actual (variable) string length returned by s.length(). The actual allocated memory size is returned by s.capacity() and could be greater than length().
Example using vector array:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string s = "01234";
cout << "s[" << s.length() << "]=\"" << s << "\"" << endl;
cout << "sizeof(s)=" << sizeof(s) << " (implementation dependent)" << endl;
cout << endl;
s += "56789012345";
cout << "s[" << s.length() << "]=\"" << s << "\"" << endl;
cout << "sizeof(s)=" << sizeof(s) << " (implementation dependent)" << endl;
cout << endl;
vector<string>vs={"12","23","345","456","567","67888","7899999999","8","9876543210"};
cout << "vs[" << vs.size() << "]={";
size_t sz=0;
for (size_t index=0; index<vs.size(); index++)
{
sz+=vs[index].size();
if (index>0)
cout << ",";
cout << "\"" << vs[index] << "\":" << vs[index].size();
}
cout << "}:" << sz << endl;
cout << "sizeof(vs)=" << sizeof(vs) << " (implementation dependent)" << endl;
return 0;
}
Result:
s[5]="01234"
sizeof(s)=8 (implementation dependent)
s[16]="0123456789012345"
sizeof(s)=8 (implementation dependent)
vs[9]={"12":2,"23":2,"345":3,"456":3,"567":3,"67888":5,"7899999999":10,"8":1,"9876543210":10}:39
sizeof(vs)=24 (implementation dependent)
template< class T, size_t N >
std::size_t Length(const T(&)[N])
{
return N;
};
std::cout << Length(another_array) << std::endl;
In String vector use size() method
Something to be aware of: text can be represented in different methods. An array of text can also be represented in different methods.
Array of pointers to C-Style strings
A common method is to have an array of pointers to char. The issue is that the size of the array doesn't represent the size of all of the text. Also, the ownership of the data or pointer must also be established, as the text may have to be delete (and can the callee delete the text or does the caller?). Because it is an array, the size of the array must always accompany the array in all parameters (unless the array is always a fixed size).
Array of char - packed text
Another method is to pass an array of char and have the strings contiguous in the array. One string follows the termination char of the previous. With this array, the total size of all of the strings is represented, no wasted space. Again, with arrays, the size of the array must accompany the array when passed around.
Array of std::string
In C++, text can be represented using std::string. In this case, the array represents the quantity of strings (similar to the array of C-Strings above). To get the total size of all the strings, one must sum up the size of each individual string. Since this is an array, the size of the array must be passed also.
Summary
During run-time array sizes must accompany the array when the array is passed around. sizeof is only processed at compile time. A simpler structure is std::vector, which handles size and memory allocation dynamically.