template <class T>
void swap(T& a, T& b){
T tmp = a; a = b; b = tmp;
}
I am reading a book and it tells me that the code above will not work for arrays unless we overload the '=' operator. I don't understand why it shouldn't work though. Are we not switching around the pointers to the first index of the arrays?
First of all, if you pass arrays as arguments the type T will be deduced to be an array type, and that leads to problem as you can not assign an array only copy them.
Then your misconception that you can just switch pointers around, that can't be done. If you have two pointers, swapping them will work fine but you can't just switch around arrays like that. And it won't be possible to use pointers to the arrays using the address-of operator directly in the call either, as that will attempt to bind references to temporary values which are not possible.
The only solution to "swap arrays" using your function is something like
char array1[...] = { ... };
char array2[...] = { ... };
char* pointer_to_array1 = array1;
char* pointer_to_array2 = array2;
swap(pointer_to_array1, pointer_to_array2);
// After call, pointer_to_array1 will point to the first element of array2
// and pointer_to_array2 will point to the first element of array1
Are we not switching around the pointers to the first index of the arrays?
There is no such thing. It sounds like your mental model of a C-style array is a pointer that points to some elements. However this is wrong. In fact the C-style array is just the elements, there is no pointer.
We can form a temporary pointer to the first element when we need one but there is not such a pointer stored along with the array storage.
Like any other object, an array lives at the same address for its entire lifetime. Swapping two arrays can only be done by swapping the contents of every element.
Related
I want to know whether a pointer is pointing to an array or single integer. I have a function which takes two pointer (int and char) as input and tell whether a pointer is pointing to an array or single integer.
pointer=pointer+4;
pointer1=pointer1+4;
Is this a good idea?
Like others have said here, C doesn't know what a pointer is pointing to. However if you should choose to go down this path, you could put a sentinel value in the integer or first position in the array to indicate what it is...
#define ARRAY_SENTINEL -1
int x = 0;
int x_array[3] = {ARRAY_SENTINEL, 7, 11};
pointer = &x_array[0];
if (*pointer == ARRAY_SENTINEL)
{
// do some crazy stuff
}
pointer = &x;
if (*pointer != ARRAY_SENTINEL)
{
// do some more crazy stuff
}
That's not a good idea. Using just raw pointers there's no way to know if they point to an array or a single value.
A pointer that is being used as an array and a pointer to a single values are identical - they're both just a memory address - so theres no information to use to distinguish between them. If you post what you want to ultimately do there might be a solution that doesn't rely on comparing pointers to arrays and single values.
Actually pointers point to a piece of memory, not integers or arrays. It is not possible to distinguish if an integer is single variable or the integer is an element of array, both will look exactly the same in memory.
Can you use some C++ data structures, std::vector for example?
For C++ questions, the answer is simple. Do not use C-style dynamic arrays in C++. Whenever you need a C-style dynamic array, you should use std::vector.
This way you would never guess what the pointer points to, because only std::vector will be holding an array.
I have a class that has a large 2 dimensional array in it. It used to be a dynamic array allocated on the heap and now it is statically sized which I prefer.
private:
int fontTextureCoords_[100][7];
I had to add the type casting to the the accessor in order to return the array for access outside the class which is currently working okay, but I'm not sure it is safe or the correct way to handle this.
public:
inline int **getFontTextureCoords()
{
return (int**)fontTextureCoords_;
}
Is this safe / the correct way to do this or is there a more preferred method for returning a pointer to a multi-dimensional array?
That's not the correct way to do that and shouldn't compile. A 2d array is not convertible to a pointer to pointer. You'd have to return a pointer to an array, which is easiest to write using a typedef:
using T = int[7];
inline T* getFontTextureCoords() { return fontTextureCoords_; }
Although it'd be much better to just return a reference the full array:
using T = int[100][7];
inline T& getFontTextureCoords() { return fontTextureCoords_; }
You could also just std::array<std::array<int, 7>, 100>.
Maybe this diagram shows you the difference between the two types of multi-dimensional array declarations. (Sometime people don't understand this.)
The first one says a is a single block of 100 consecutive 7-int chunks, or 700 ints total, all together in one piece.
The second says a is an array of pointers, where each pointer points to a different chunk of ints, scattered all over memory.
The compiler needs to know this, because if you write a[i][j] it has to generate totally different code.
Casting an array such as int fontTextureCoords_[100][7]; to an int** is not right. It leads to undefined behavior.
If it is not too much, change getFontTextureCoords to:
inline int (*getFontTextureCoords()) [7]
{
return fontTextureCoords_;
}
and use it as:
int (*ptr)[7] = getFontTextureCoords();
If you have the option of using std::vector or std::array, it will be better to use them.
There are no multi-dimensional arrays in C/C++. There are only single dimenstional arrays. You can have a single-dimensional array, with every element of it being another single dimensional array. While there seem to be no difference, it is there and is very important.
This is exactly way transitive logic doesn not work. Everybody has gone through it. 'If single-dimensional arrays are passed as a pointer to the first elelement, 2-D arrays should be passed as a pointer to pointer to first element, etc'. But since it is not a two-dimensional array, but array of arrays, the logic can not be applied.
You can reason about it in the following way. Let's say, you have an array of types X.
X x[10];
How do you access element number 5? Easy -
x[5] = 42;
But what compiler does when it sees it? It does approximately this:
*(&x[0] + 5) = 42;
So it takes the address of the first element, and adds 5 to it to get to the address of your 5th element. But what adding 5 means? In bytes, how many bytes should be skipped from address of beginning of the array to arrive at requested memory location? Of course, 5 * sizeof(X). Now, if you have '2-D' array, declared like this:
X x[2][3];
And you try to work with it through the pointer to pointer:
px = (X**)x;
px[3][4] = 42;
Remember, to genereate the code for [][], compiler needs to express in the way of *(px + ). And something has to be the size of the array (as elements of your array are arrays). But you need to know array size for this, and as you can see, your px does not have any array size encoded in it. The only size it know is size of X, which is not enough.
Hope it makes sense, and explains why you can't use int** instead of x[][].
This is my first question :)
double MyArray[][6];
double* Myptr = MyArray[0];
So i've been wondering why, in pointer Arithmetic, I can notate a pointer to move in a single dimension like this,
*(Myptr + i);
but if i try to move through the dimensions of the array using a for loop it won't let me
*(*(Myptr + i) + j);
However it does let me use this notation with the array itself.
*(*(MyArray + i) + j);
I wanted to know why is this a restriction? or maybe i am writing it down incorrectly.
Myptr is a pointer to double, so *(Myptr + i) is a double, and while you can add j to that, you cannot dereference the result.
Had you declared Myptr like this:
double (*Myptr)[6] = MyArray;
then Myptr would be a pointer to an array of 6 doubles. Consequently *(Myptr + i) would be a double[6], and the expression would work.
That you can index arrays using this syntax is unfortunately surprising to people who see it the first time and have never been taught about pointer decay. A funny thing about arrays in C and C++ is that they decay into pointers in almost all circumstances. What this means is that very nearly always when you use an array (exceptions exist), the array is implicitly converted to a pointer to its first element and the rest is done with pointer arithmetic.
For example, this is the case when you write MyArray[i]. The standard defines MyArray[i] to mean *(MyArray + i) (the standard uses more parentheses, but this is what it boils down to), which makes sense when you understand that MyArray decays to a pointer, i is added to this pointer, and the resulting pointer is dereferenced. It also explains why i[MyArray] is equally valid (if in bad style).
In the context of multidimensional arrays, it is important to understand that a multidimensional array is merely an array of arrays. MyArray is, in your case, an array of arrays of doubles. MyArray[0] is, then, an array of doubles. In pointer decay, MyArray decays to a pointer to array of doubles, and when you dereference that pointer and work with the array it points to, then that array also decays to a pointer (to double) when you work with it. It's decay all the way down.
MyArray has type double[][6] and MyPointer has type double*.
Now arrays and pointers are different, but this is not important in this context. Both variables have array/pointer thingies in their types, but My Array has two (count them: [] and [6]) and MyPointer has only one (count it: *). Which is why you can apply dereferencing (that's the * operator) to MyArray twice, and to MyPointer only once.
Now if you want to have a pointer that can be used in much the same way you use MyArray, this is possible, but its type will not be double** (because arrays and pointers are different). You write it this way:
double (*MyPointer2)[6] = MyArray;
This one has two array/pointer thingies in its type so you can apply dereferencing twice to it.
In this case, MyPtr is only one dimensional, because it was assigned to a specific "array" in MyArray.
Because Myptr is a double*. A pointer to a double. It has no knowledge of the array dimensions.
This question already has answers here:
Why doesn't C++ support functions returning arrays?
(10 answers)
Closed 10 years ago.
I've got a syntax question in C++ about returning an array. When we pass in an array, when can do like this:
void merge_sort(int input_array[], int size);//notice the first parameter
I know this works:
int* merge_sort(int input_array[], int size){
//do something with input_array
return new int[2]; //dummy array
}
Question:
int[] merge_sort(int input_array[], int size){ //Question is on return type, wont compile
//do something with input_array
return new int[2]; //dummy array
}
return int* succeed. Why returning int [] fail?
In both C and C++, you cannot either pass an array as an argument to a function, or return an array as a function result.
Yes, the syntax can make it look like you're passing an array argument:
void func(int param[]) {
// ...
}
...
int arr[10];
func(arr);
but in fact that's just passing a pointer to the array's first element. The parameter definition int param[] is adjusted; it's exactly equivalent to int *param. And an expression of array type, in most contexts, is implicitly converted to a pointer its first element.
That's why you need to pass the size as a separate argument.
Using only C features, there are several ways to do something like returning an array:
A function can return a pointer to the first element of a static array. This has some disadvantages: the size has to be fixed, and multiple callers get pointers to the same object.
A function can receive a pointer to the first element of an array, passed in by the caller. This places the burden of allocating and deallocating the array on the caller.
A function can return a pointer to the first element of a dynamically allocated (malloc() in C, new in C++) array. This requires the caller to deallocate the array.
C++ provides a rich set of library classes that can take care of all this for you.
Recommended reading: Section 6 of the comp.lang.c FAQ.
You can pass structs as arguments, and return them as function results, and structs can contain arrays as members. But that's not as useful as you might think. An array that's a member of a struct must have a fixed size; most useful code that operates on arrays can handle dynamic sizes.
Why would you want to return anything in the first place?
Array is not really "passed" to the function (no copy of the elements is made), only the pointer to it's beginning is. When the function rearranges the array elements, it is doing so in the original array. After the function exits, the calling code can simply continue to use the old (now-sorted) array.
In other words, the function produces a side-effect.
I know this works:
int* merge_sort(int input_array[], int size){
//do something with input_array
return new int[2]; //dummy array
}
(Assuming you actually need to return...)
Well it "works", but is very dangerous. The caller needs to be aware it needs to free the returned array (otherwise a memory leak ensues), and it needs to be aware it must use delete[] and not just delete (otherwise an undefined behavior ensues), which is distinctly non-obvious based only on the return type (which is just a pointer). The caller might also be in doubt whether the input_array is freed inside the function or not.
Even if you have documented all that, it's extremely easy for the caller to make a mistake. It's much better to use the facilities provided by modern C++ instead: for example, you could return an std::vector.
you should be using a vector in this approach, in your project include and then use a vector almost as u would with an array.
u can have a look at vectors here: http://msdn.microsoft.com/en-us/library/vstudio/9xd04bzs.aspx
the great thing about vectors is that they are dynamically scaling for your projects and would not create any memory leaks or such due to buffer overflow's, its much like an ArrayList
In C++ how can I pass an array as a reference when I don't know the size at compile time? So far, I found out that the only way to make it work is to use something like
const double( &numbers ) [size]
but it means that I need to know the size of the array at compile time, thus I cannot use it in an external function.
My questions are:
If I don't pass an array as a ( const double( &numbers ) [length] ), because for example I don't know its size, how do I make sure that it doesn't get copied, but it is referenced?
If I pass an array like in the above example, ( double array[] ) is it referenced or is it copied?
The other answers are great, but no one mention using templates to handle this. You should still make your function take a pointer and a size, but templates can fill that automatically for you:
void f( double const numbers[], std::size_t length )
{ ... }
template< std::size_t Length >
void f( double const (&numbers)[ Length ] )
{
return f( numbers, Length );
}
In C++, you should use std::vector.
In C/C++, you can't pass arrays as a copy. Arrays are always passed by reference.
EDIT
In C++, arrays passed by reference has different meaning. In both C and C++, arrays decay into a pointer to the first element of the array. Please check the comments below.
If I don't pass an array as a ( const double( &numbers ) [length] ),
because for example I don't know its size, how do I make sure that it
doesn't get copied, but it is referenced?
Yes, it means you're passing an array as reference,
void Foo(const double( &numbers ) [length]);
Note that the length is a constant integer.
If I pass an array like in the above example, ( double array[] ) is it
referenced or is it copied?
No, it is not copied. It means you're passing a pointer to your array which is equivalent to,
void Foo(const double *length);
A couple things:
C++ doesn't allow variable-sized arrays anyway. So all your arrays will need to have known sizes at compile time. So I'm not entirely sure if your initial question is even applicable since you won't be able to make an array with an unknown size in the first place.
When you pass an array, it is done by reference. It is not copied.
In any case, you'll probably want to consider using vector instead.
EDIT : See comments.
double average(const double *arr, size_t len){
// Compute average
return accumulate(arr, arr + len, 0) / (double)len;
}
int main(){
double array[10] = // Initialize it
cout << average(array, 10) << endl;
// Alternatively: This could probably be made a macro.
// But be careful though since the function can still take a pointer instead
// of an array.
cout << average(array, sizeof(array) / sizeof(double)) << endl;
return 0;
}
In C++, an array's name is just a constant pointer to its first element. A constant pointer means a pointer that's capable of changing whatever it points to, but it can't be changed to point to something else.
This means that whenever you pass an array, you're actually passing a constant pointer to that array. In other words, you're already passing it by reference, no need for extra efforts. To be more accurate, what is actually copied is that constant pointer, so the final (hopefully not-that-confusing) phrasing is that you're passing a constant pointer to the array by value.
If you don't know your array's size at compile time, just use a (normal) pointer to your data type instead of an explicit array. So whatever is T my_array[] (where T is a type, like int, double or even one of your classes) becomes T* my_array, and the syntax is exactly the same hereafter... my_array[i] will work fine (another syntax also exists, but not as elegant). For initialization, use the new operator:
T* my_array;
my_array = new T[3];
or
T* my_array;
my_array = new T[x];
where x is an integer (not necessarily constant as is the case with normal arrays). This way you can take this x from the user at runtime and create your "array" then. Just take care not to forget delete[] my_array after you finish using it to avoid memory leaks.
[Final Note] Using such a dynamically allocated array is a good choice only when you know exactly how many elements you want... either at compile time or even at runtime. So, for example, if after the user supplies his x you'll exactly be using those, that's fine. Otherwise you're facing the danger of overflowing your array (if you need more than x) - which usually crashes the application - or just wasting some space. But even if this is the case, you'll implement most of the functions you need for array manipulation yourself. That's why it's preferable to use containers provided by the C++ Standard Library, like std::vector (as Donotalo mentioned). I just wanted to elaborate on that point more.
Other languages like Java and Python do store the length of arrays at runtime. In C++ arrays, the length of the array is not stored. That means you need to store it manually somewhere.
Whenever you have a fixed size array on your code, the compiler knows the size of the array since it is reading it from the source code itself. But once the code get compiled, that length information is lost. For example:
void f1(double array[10]) {...}
The compiler won't enforce the size of the array. The following code will silently compile since the array parameter of f1 us just a pointer to the first element of an array:
void h1() {
double a[10];
double b[5];
f1(a); // OK.
f2(b); // Also OK.
}
Since the compiler ignores the static size of the array when passing it to a function, the only way you have to know the size of an arbitrarily sized array passed as a reference is to explicitly state the size:
void f2(double array[], size_t array_size) {...}
Then you can call that function with any array:
void h2() {
double a[10];
double b[19];
f2(a, sizeof(a) / sizeof(a[0]));
f2(b, sizeof(a) / sizeof(a[0]));
}
The parameter array_size contains the actual size of the array.
As a note, sizeof(array) only works on statically defined arrays. When you pass that array to another functions, the size information is lost.
An array is not the same as a pointer. However, an array of undefined size like the parameter of f2 is just a pointer to the first double element in the sequence:
void f3(double array*, size_t array_size) {...}
For any practicar purpose, f2 and f3 are equivalent.
This is exactly how std::vector works. Internally, a vector is a class with two fields: a pointer to the first element, and the number of elements in the vector. This makes things a little simpler when you want to accept an array of any size as a parameter:
void g(std::vector& v) {...}