I'm new to programming and I want to know if this is a valid way to print the address of each element in a vector.
#include <iostream>
#include <vector>
using namespace std;
void printAdress( vector<int> & a ) {
vector<int*> ptr;
for (int i = 0; i < a.size(); i++) {
ptr.push_back(&a[i]);
}
for (int i = 0; i < ptr.size(); i++) {
cout << ptr[i] << "\n";
}
}
int main () {
vector<int> a = {1, 2, 3, 4, 5, 6, 7, 8, 9};
printAdress(a);
return 0;
}
Is this error prone? Is there a more efficient way to do this? Am I using unnecessary memory? I'd love some feedback.
In C++, arrays (including the data of a std::vector container) are contiguous blocks of data elements. Thus, the address of the ith element of such an array (or vector) is just the address of the array's first element plus the value of i. (The addend is actually i * sizeof(element), but that size factor is automatically taken into account when performing pointer arithmetic in C++.)
So:
As mentioned in the comments, your printAdress function has no need to create a new vector (which is lost when the function returns).
There is no need to take the address of each element in the vector, once the address of its 'base' (which is available via the data() member function of the std::vector class) is known.
Here's a reasonably efficient example:
void printAdress(const std::vector<int>& a)
{
const int* base = a.data();
const size_t n = a.size();
for (size_t i = 0; i < n; ++i) std::cout << (base + i) << std::endl;
}
An alternative syntax. 'Behind the scenes' this is very likely doing the same as #Adrian Mole's answer (which usefully explains the fundamental concept of C++ pointer arithmetic), but illustrates a few of the other language features which the OP might encounter on their C++ journey:
template<typename T>
void printAddress(const std::vector<T>& v)
{
for (auto& e : v) std::cout << &e << "\n";
}
This allows the writing of:
using namespace std;
vector<int> a = { 1,2,3,4,5 };
printAddress(a);
vector<double> b = { 1.0,2.0,3.0,4.0,5.0 };
printAddress(b);
without any additional code in printAddress().
NB: This code doesn't compile for vector<bool> which stores the internal data in a different way.
Related
I am trying to move from arrays to vectors in cpp for problem-solving and its overall benefits. I am facing some issues here even though this logic works on arrays.
#include <iostream>
#include <vector>
using namespace std;
void PrintArray(vector<int> v) { // O(n)
for (int i=0; i<v.size(); i++)
cout << v[i] << " ";
cout << endl;
}
void LF1(vector<int> A) { // O(n)
int temp = A[0],i;
for (i=0; i<A.size()-1; i++)
A.at(i) = A.at(i+1);
A.at(i)=temp;
// PrintArray(A); <-- shows updated array here
}
void LF(vector<int> A, int d) {
d = d % (A.size());
cout << "d%n: " << d << endl;
for (int j=0; j<d; j++)
LF1(A);
PrintArray(A);
}
int main(int argc, char const *argv[]) {
vector<int> A;
int d;
for(int i=1; i<6; i++)
A.push_back(i);
PrintArray(A);
cout << "Enter number of Left rotations to perform : ";
cin >> d;
LF(A,d);
return 0;
}
Problem 1: When I am calling LF1 inside of LF it returns the same array without rotating but when I write the code for LF1 inside of LF it seems to rotate.
Problem 2: The PrintArray() prints the rotated array only when called from LF1() or just immediately after its code when written (instead of calling LF1()) in LF() when causes it to print the array d times. Where d is the required rotations.
Regarding what you're doing wrong...you are passing the vectors by value. You don't expect changes to an integer to affect it in the caller when you pass it as a value...
void SomeFunction(int i) {
i = i + 1;
printf("Inside SomeFunction %d\n", i); // changed, 11
}
int i = 10;
SomeFunction(i);
printf("Outside SomeFunction %d\n", i); // unchanged, 10
...if you wanted to see a change, you would have to pass a pointer, such as int *pi, and then update it as *pi = *pi + 1;
The same principle applies to vectors and other C++ classes. If you just pass it as a value, the whole vector is copied. (Well, if it needs to be, a temporary could just be reused). But for now think of it as being copied: just as there's a difference between passing an integer and a pointer-to-an-integer, there's a difference between a vector and a pointer-to-a-vector.
You could pass a pointer to the vector if you intend to change it...or... C++ offers another tool called the reference, where references are very much like pointers but with a few differences. If you just changed your arguments to vector<int> &A then your code should work, because the arrays would be "passed by reference" instead of getting copied when they are "passed by value", so changes would take effect. If you don't want a function to need to be able to modify an array but still want to avoid the copy, pass by const reference, e.g. const vector<int> &A (e.g. this is what your PrintArray() should use).
You might not want to get too hung up on the details of references for now, other than thinking of it as a "convenient kind of pointer where you don't have to put the * on all the places you want to dereference". But in case you want to know more specifics:
What are the differences between a pointer variable and a reference variable in C++?
I am facing some issues here even though this logic works on arrays.
And this is probably the source of your confusion. Which comes from the fact that C-style arrays decay into pointers under the hood:
Passing an Array by reference in C
I think that's something that it's reasonable to be confused by, given that other types (such as integers and vectors) don't. It's just a quirk of C, that C++ inherited. So when C++11 wanted to clean that up, a wrapper class called std::array was introduced:
https://embeddedartistry.com/blog/2017/6/28/an-introduction-to-stdarray
https://en.cppreference.com/w/cpp/container/array
But C++ also has an algorithm to do rotation...
So if you want to see a good example of how this would be done, it's a place to start:
#include <vector>
#include <iostream>
#include <algorithm>
int main() {
std::vector<int> v{1, 2, 3, 4};
std::rotate(v.begin(), v.begin() + 1, v.end());
for (auto &i : v)
std::cout << i << " ";
std::cout << "\n";
}
That will get you 2 3 4 1. The documentation has other examples, read through:
https://en.cppreference.com/w/cpp/algorithm/rotate
This question already has answers here:
When a function has a specific-size array parameter, why is it replaced with a pointer?
(3 answers)
Closed 7 years ago.
I am aware that an array can be passed to a function in quite a few ways.
#include <iostream>
#include <utility>
using namespace std;
pair<int, int> problem1(int a[]);
int main()
{
int a[] = { 10, 7, 3, 5, 8, 2, 9 };
pair<int, int> p = problem1(a);
cout << "Max =" << p.first << endl;
cout << "Min =" << p.second << endl;
getchar();
return 0;
}
pair<int,int> problem1(int a[])
{
int max = a[0], min = a[0], n = sizeof(a) / sizeof(int);
for (int i = 1; i < n; i++)
{
if (a[i]>max)
{
max = a[i];
}
if (a[i] < min)
{
min = a[i];
}
}
return make_pair(max,min);
}
My code above passes only the first element while it should be passing an array (or technically, a pointer to the array) and hence, the output is 10, 10 for both max and min (i.e. a[0] only).
What am I doing wrong, I guess this is the correct way.
The contents of the array are being passed to the function. The problem is:
n = sizeof(a) / sizeof(int)
Does not give you the size of the array. Once you pass an array to a function you can't get its size again.
Since you aren't using a dynamic array you can use a std::array which does remember its size.
You could also use:
template <int N>
void problem1(int (&a) [N])
{
int size = N;
//...
}
No, you simply cannot pass an array as a parameter in C or C++, at least not directly.
In this declaration:
pair<int, int> problem1(int a[]);
even though a appears to be defined as an array, the declaration is "adjusted" to a pointer to the element type, so the above really means:
pair<int, int> problem1(int* a);
Also, an expression of array type is, in most contexts, implicitly converted to a pointer to the array's initial element. (Exceptions include an array as the operand of sizeof or unary &). So in a call to the above function:
int arr[10];
problem1(arr);
the array expression arr is equivalent to &arr[0], and that address (pointer value) is what's passed to the function.
Of course you can write code that does the equivalent of passing an array. You can make the array a member of a structure (but then it has to be of fixed length). Or you can pass a pointer to the initial element and pass a separate parameter containing the actual length of the array object.
Or you can use one of the C++ standard library classes that implement array-like data structures; then the length can be taken directly from the parameter.
I highly recommend reading section 6 of the comp.lang.c FAQ, which covers arrays and pointers. It's applicable to C++ as well (though it doesn't mention the C++ standard library).
In C++ language a function parameter declared as int a[] is immediately interpreted as and is equivalent to int *a parameter. Which means that you are not passing an array to your function. You are passing a pointer to the first element of an array.
Trying to apply the sizeof(a) / sizeof(int) technique to a pointer is useless. It cannot possibly produce the size of the argument arraay.
One alternative that hasn't been mentioned is writing your code as a template, and passing the array by reference so the template can deduce the size of the array:
template <class T, size_t n>
pair<T, T> problem1(T(&a)[n]) {
T max = a[0], min = a[0];
for (size_t i = 1; i < n; i++) {
if (a[i]>max) {
max = a[i];
}
if (a[i] < min) {
min = a[i];
}
}
return make_pair(max, min);
}
Note, however, that this will only work if you pass a real array, not a pointer. For example, code like this:
int *b = new int[10];
for (int i = 0; i < 10; i++)
b[i] = rand();
auto result = problem1(b);
...won't compile at all (because we've defined problem1 to receive a reference to an array, and b is a pointer, not an array).
as in the title is it possible to join a number of arrays together without copying and only using pointers? I'm spending a significant amount of computation time copying smaller arrays into larger ones.
note I can't used vectors since umfpack (some matrix solving library) does not allow me to or i don't know how.
As an example:
int n = 5;
// dynamically allocate array with use of pointer
int *a = new int[n];
// define array pointed by *a as [1 2 3 4 5]
for(int i=0;i<n;i++) {
a[i]=i+1;
}
// pointer to array of pointers ??? --> this does not work
int *large_a = new int[4];
for(int i=0;i<4;i++) {
large_a[i] = a;
}
Note: There is already a simple solution I know and that is just to iteratively copy them to a new large array, but would be nice to know if there is no need to copy repeated blocks that are stored throughout the duration of the program. I'm in a learning curve atm.
thanks for reading everyone
as in the title is it possible to join a number of arrays together without copying and only using pointers?
In short, no.
A pointer is simply an address into memory - like a street address. You can't move two houses next to each other, just by copying their addresses around. Nor can you move two houses together by changing their addresses. Changing the address doesn't move the house, it points to a new house.
note I can't used vectors since umfpack (some matrix solving library) does not allow me to or i don't know how.
In most cases, you can pass the address of the first element of a std::vector when an array is expected.
std::vector a = {0, 1, 2}; // C++0x initialization
void c_fn_call(int*);
c_fn_call(&a[0]);
This works because vector guarantees that the storage for its contents is always contiguous.
However, when you insert or erase an element from a vector, it invalidates pointers and iterators that came from it. Any pointers you might have gotten from taking an element's address no longer point to the vector, if the storage that it has allocated must change size.
No. The memory of two arrays are not necessarily contiguous so there is no way to join them without copying. And array elements must be in contiguous memory...or pointer access would not be possible.
I'd probably use memcpy/memmove, which is still going to be copying the memory around, but at least it's been optimized and tested by your compiler vendor.
Of course, the "real" C++ way of doing it would be to use standard containers and iterators. If you've got memory scattered all over the place like this, it sounds like a better idea to me to use a linked list, unless you are going to do a lot of random access operations.
Also, keep in mind that if you use pointers and dynamically allocated arrays instead of standard containers, it's a lot easier to cause memory leaks and other problems. I know sometimes you don't have a choice, but just saying.
If you want to join arrays without copying the elements and at the same time you want to access the elements using subscript operator i.e [], then that isn't possible without writing a class which encapsulates all such functionalities.
I wrote the following class with minimal consideration, but it demonstrates the basic idea, which you can further edit if you want it to have functionalities which it's not currently having. There should be few error also, which I didn't write, just to make it look shorter, but I believe you will understand the code, and handle error cases accordingly.
template<typename T>
class joinable_array
{
std::vector<T*> m_data;
std::vector<size_t> m_size;
size_t m_allsize;
public:
joinable_array() : m_allsize() { }
joinable_array(T *a, size_t len) : m_allsize() { join(a,len);}
void join(T *a, size_t len)
{
m_data.push_back(a);
m_size.push_back(len);
m_allsize += len;
}
T & operator[](size_t i)
{
index ix = get_index(i);
return m_data[ix.v][ix.i];
}
const T & operator[](size_t i) const
{
index ix = get_index(i);
return m_data[ix.v][ix.i];
}
size_t size() const { return m_allsize; }
private:
struct index
{
size_t v;
size_t i;
};
index get_index(size_t i) const
{
index ix = { 0, i};
for(auto it = m_size.begin(); it != m_size.end(); it++)
{
if ( ix.i >= *it ) { ix.i -= *it; ix.v++; }
else break;
}
return ix;
}
};
And here is one test code:
#define alen(a) sizeof(a)/sizeof(*a)
int main() {
int a[] = {1,2,3,4,5,6};
int b[] = {11,12,13,14,15,16,17,18};
joinable_array<int> arr(a,alen(a));
arr.join(b, alen(b));
arr.join(a, alen(a)); //join it again!
for(size_t i = 0 ; i < arr.size() ; i++ )
std::cout << arr[i] << " ";
}
Output:
1 2 3 4 5 6 11 12 13 14 15 16 17 18 1 2 3 4 5 6
Online demo : http://ideone.com/VRSJI
Here's how to do it properly:
template<class T, class K1, class K2>
class JoinArray {
JoinArray(K1 &k1, K2 &k2) : k1(k1), k2(k2) { }
T operator[](int i) const { int s = k1.size(); if (i < s) return k1.operator[](i); else return k2.operator[](i-s); }
int size() const { return k1.size() + k2.size(); }
private:
K1 &k1;
K2 &k2;
};
template<class T, class K1, class K2>
JoinArray<T,K1,K2> join(K1 &k1, K2 &k2) { return JoinArray<T,K1,K2>(k1,k2); }
template<class T>
class NativeArray
{
NativeArray(T *ptr, int size) : ptr(ptr), size(size) { }
T operator[](int i) const { return ptr[i]; }
int size() const { return size; }
private:
T *ptr;
int size;
};
int main() {
int array[2] = { 0,1 };
int array2[2] = { 2,3 };
NativeArray<int> na(array, 2);
NativeArray<int> na2(array2, 2);
auto joinarray = join(na,na2);
}
A variable that is a pointer to a pointer must be declared as such.
This is done by placing an additional asterik in front of its name.
Hence, int **large_a = new int*[4]; Your large_a goes and find a pointer, while you've defined it as a pointer to an int. It should be defined (declared) as a pointer to a pointer variable. Just as int **large_a; could be enough.
How can I pass a two or multi dimensional array as a parameter of a function without defining its size??
Here is my example code:
void test(int *a) {
a[0][0] = 100;
}
int main() {
int a[2][2];
test(a);
cout<<a[0][0];
}
You can use a template for static sizes
template<int first, int second> void func(int(&array)[first][second]) {
}
Or a vector of vector for dynamic sizes
void func(std::vector<std::vector<int>> array) {
}
However, what you most definitely cannot do is use an int**. An int[] will decay to an int* but an int[][] will decay to an int*[]. Think about it- else, how would the language differentiate between an array of pointers, and a multi-dimensional array of values? You really should never use primitive arrays anyway, they're begging for trouble with no safety and implicit conversions up the wazoo. Grab a nice, safe std::array (or boost::array if you're in C++03) for static arrays, or std::vector for dynamic arrays.
If you're working exclusively with statically-sized, stack-allocated arrays, then a function template will do exactly what you're asking for:
#include <cstddef>
#include <ostream>
#include <iostream>
template<std::size_t N, std::size_t M>
void func(int (&arr)[N][M])
{
std::cout << "int[" << N << "][" << M << "]\n";
for (std::size_t n = 0; n != N; ++n)
for (std::size_t m = 0; m != M; ++m)
std::cout << arr[n][m] << ' ';
std::cout << '\n' << std::endl;
}
int main()
{
int i1[2][3] = { { 4, 5, 6 }, { 7, 8, 9 } };
int i2[4][2] = { { 1, 3 }, { 5, 7 }, { 9, 11 }, { 13, 15 } };
func(i1);
func(i2);
}
Passing the pointer to the array. For example, if you have a bidimensional int array you'll need to pass int** p, along with the dimensions of the array.
For built-in arrays, you have to specify the size of all dimensions but the last dimension or indexing won't work.
If your goal is just to have a function that takes multi-dimensional arrays of any size, I'd consider boost::multi_array_ref (or boost::const_multi_array_ref)
Update:
Since passing by pointer appears to be the answer that's getting the most attention (although I think the multi_array_ref is good... unless boost isn't available or something) then here's an example that flattens the array and doesn't limit you by array dimensions (although you still need size information to make it useful)
void f(int* array /* should probably pass in the size here - in this case, 4 */)
{
array[3] = 9;
}
int main()
{
int array[2][2] = { {1,2}, {3,4} };
// Note: The array is flattened here. If you truly need to remember the multi-dimensional nature, you need to pass in enough information to specify all the dimensions... maybe something like a vector<size_t> (that's what the multi_array_ref uses). I guess if you have a limited number of dimensions then a couple size_t will work for you
test(&array[0][0]);
std::cout << array[1][1] << std::endl;
return 0;
}
int a[][]
Can be passed as:
function name(int **arr) {
//your code, you can then access it just like you would have accesses your array:
arr[3][2]
}
How do I reliably get the size of a C-style array? The method often recommended seems to be to use sizeof, but it doesn't work in the foo function, where x is passed in:
#include <iostream>
void foo(int x[]) {
std::cerr << (sizeof(x) / sizeof(int)); // 2
}
int main(){
int x[] = {1,2,3,4,5};
std::cerr << (sizeof(x) / sizeof(int)); // 5
foo(x);
return 0;
}
Answers to this question recommend sizeof but they don't say that it (apparently?) doesn't work if you pass the array around. So, do I have to use a sentinel instead? (I don't think the users of my foo function can always be trusted to put a sentinel at the end. Of course, I could use std::vector, but then I don't get the nice shorthand syntax {1,2,3,4,5}.)
In C array parameters in C are really just pointers so sizeof() won't work. You either need to pass in the size as another parameter or use a sentinel - whichever is most appropriate for your design.
Some other options:
Some other info:
for C++, instead of passing a raw array pointer, you might want to have the parameter use something that wraps the array in a class template that keeps track of the array size and provides methods to copy data into the array in a safe manner. Something like STLSoft's array_proxy template or Boost's boost::array might help. I've used an array_proxy template to nice effect before. Inside the function using the parameter, you get std::vector like operations, but the caller of the function can be using a simple C array. There's no copying of the array - the array_proxy template takes care of packaging the array pointer and the array's size nearly automatically.
a macro to use in C for determining the number of elements in an array (for when sizeof() might help - ie., you're not dealing with a simple pointer): Is there a standard function in C that would return the length of an array?
A common idiom mentioned in GNU Libstdc++ documentation is the lengthof function:
template<typename T, unsigned int sz>
inline unsigned int lengthof(T (&)[sz]) { return sz; }
You can use it as
int x[] = {1,2,3,4,5};
std::cerr << lengthof(x) << std::endl;
Warning: this will work only when the array has not decayed into a pointer.
How about this?..
template <int N>
void foo(int (&x)[N]) {
std::cerr << N;
}
You can either pass the size around, use a sentinel or even better use std::vector. Even though std::vector lacks initializer lists it is still easy to construct a vector with a set of elements (although not quite as nice)
static const int arr[] = {1,2,3,4,5};
vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );
The std::vector class also makes making mistakes far harder, which is worth its weight in gold. Another bonus is that all C++ should be familiar with it and most C++ applications should be using a std::vector rather than a raw C array.
As a quick note, C++0x adds Initializer lists
std::vector<int> v = {1, 2, 3, 4};
You can also use Boost.Assign to do the same thing although the syntax is a bit more convoluted.
std::vector<int> v = boost::assign::list_of(1)(2)(3)(4);
or
std::vector<int> v;
v += 1, 2, 3, 4;
c provides no native support for this. Once an array is passed out of its declared scope, its size is lost.
You can pass the size with the array. You can even bundle them into a structure if you always to to keep the size, though you'll have some bookkeepping overhead with that.
I also agree that Corwin's method above is very good.
template <int N>
void foo(int (&x)[N])
{
std::cerr << N;
}
I don't think anybody gave a really good reason why this is not a good idea.
In java, for example, we can write things like:
int numbers [] = {1, 2, 3, 4};
for(int i = 0; i < numbers.length(); i++)
{
System.out.println(numbers[i]+"\n");
}
In C++ it would be nice instead of saying
int numbers [] = {1, 2, 3, 4};
int size = sizeof(numbers)/sizeof(int);
for(int i = 0; i < size; i++)
{
cout << numbers[i] << endl;
}
We could take it a step further and go
template <int N>
int size(int (&X)[N])
{
return N;
}
Or if that causes problems I suppose you could write explicitly:
template < int N >
int size(int (&X)[N])
{
int value = (sizeof(X)/sizeof(X[0]));
return value;
}
Then we just have to go in main:
int numbers [] = {1, 2, 3, 4};
for(int i = 0; i < size(numbers); i++)
{
cout << numbers[i] << endl;
}
makes sense to me :-)
An array expression will have its type implicitly converted from "N-element array of T" to "pointer to T" and its value will be the address of the first element in the array, unless the array expression is the operand of either the sizeof or address-of (&) operators, or if the array expression is a string literal being used to initialize another array in a declaration. In short, you can't pass an array to a function as an array; what the function receives is a pointer value, not an array value.
You have to pass the array size as a separate parameter.
Since you're using C++, use vectors (or some other suitable STL container) instead of C-style arrays. Yes, you lose the handy shorthand syntax, but the tradeoff is more than worth it. Seriously.
Now, you can use C++11's extent and rank.
By example:
#include <iostream>
#include <type_traits>
int main()
{
int a[][3] = {{1, 2, 3}, {4, 5, 6}};
std::cout << "\nRank: : " << std::rank<decltype(a)>::value;
std::cout << "\nSize: [_here_][]: " << std::extent<decltype(a), 0>::value;
std::cout << "\nSize: [][_here_]: " << std::extent<decltype(a), 1>::value;
std::cout << "\nSize: [][]_here_: " << std::extent<decltype(a), 2>::value;
}
prints:
Rank: : 2
Size: [_here_][]: 2
Size: [][_here_]: 3
Size: [][]_here_: 0
You need to pass the size along with the array, just like it is done in many library functions, for instance strncpy(), strncmp() etc. Sorry, this is just the way it works in C:-).
Alternatively you could roll out your own structure like:
struct array {
int* data;
int size;
};
and pass it around your code.
Of course you can still use std::list or std::vector if you want to be more C++ -ish.
Since c++11, there is a very convenient way:
static const int array[] = { 1, 2, 3, 6 };
int size = (int)std::distance(std::begin(array), std::end(array))+1;