I want to call a function which requires an array of integers. How could I do this without creating a new array of integers every time I want to call the function?
This is what I want to do:
someFunction(new int[]{obj[0].getInt(), obj[1].getInt()});
instead of doing this:
int intArray[2] = {obj[0].getInt(), obj[1].getInt()};
someFunction(intArray);
Assuming you can use C++11, you can define somefunction to take an std::vector (or a std::vector const &) instead of an actual array, and then use:
somefunction({obj[0].getInt(), obj[1].getInt()});
Unlike Java, you do not need to use new on a regular basis in C++. In fact, in most well written code it's fairly unusual.
As an aside, you generally want to avoid C++'s built-in arrays, and C++11 makes it easier to do that, to the point that there's rarely a good reason to use them at all.
Related
I am trying to connect two existing codebases — one in C, the other in C++. The C++ code uses std::vector whereas the other one is based on arrays of double. I would like to pass arrays of double from the C code, perform operations on std::vectors in the C++ code, and eventually have these operations reflected in the arrays of double.
Is it possible to create a std::vector that matches the memory occupied by the array of double?
I have tried several options, but they all involve the creation of a new vector and a copy of the array of double into that vector. For instance:
void fcn(double* a, int sizeofa)
{
std::vector<double> vect_a;
vect_a.assign(a, a + sizeofa);
// operations on vect_a
for (int i=0;i<sizeofa;i++) { a[i] = vect_a[i]; }
}
As noted in the comments, std::vector manages its own memory, you can't make it use some other memory as the backing store (it would have no idea what to do if the size changed, among other issues).
But you may not need a vector at all; if you're just using vector for non-dynamic size related features, it's highly likely you could just use the functions from <algorithm> to perform the same work directly on the array that you wanted to use vector's methods to accomplish.
In C++, functions requiring a container often denote the container by Iterator pairs, which are templated. This is very convenient, especially when interfacing with external libraries, because an iterator isn't a type. It is a concept, which is just an interface that defines what a type should look like. Turns out, C style pointers are valid iterators. This means that you can use any C++ function that accepts an iterator with any C array.
So, now to answering your question. In other answers, it was made clear that you cannot make a std::vector control the memory allocated by a C array because a std::vector requires full ownership over the data because it wouldn't know how to deallocate it. You can copy the C array into a vector, but there is no point in using a std::vector unless you want it's resizing capabilities.
In summary: try not to pass std::vectors into functions because iterators are more generic. If you must avoid templates (virtual function, etc) than use a C style array because those are very flexible too, you can turn a std::vector into a C array, but the other way requires a copy.
I know this is hard if you have already made your code interface with std::vectors, in which case a copy is the only possible way. Prefer C style arrays when you don't need to resize the array, and maybe in the future std::array_view
Is there a way to use RAII when creating an array in C++, or do I have to resort to manual memory management via the "new" keyword?
EDIT: By request, some additional details:
First my disclaimer: I'm fairly novice at C++.
Now the details: I simply wanted to iterate through an existing array, SomeClass source[], and parse each element into a storage array, string results[].
So to create that storage string results[], do I need to say string results[] = new string[source.size()] or is there a way to avoid the "new" keyword here via RAII techniques?
It sounds like I'm hearing vector is the way to go. Still, wondered if it's possible with a plain old array.
In C++, especially since we're talking about RAII, we really shouldn't be using C-style arrays at all. The Standard Library provides many containers with different properties that obviate most needs for C-style arrays. By default, you should be using std::vector<> unless you have an understanding of the other containers and a compelling reason not to 1.
Judging from your comments, it looks like what you're trying to do is build an array of string data. This is simple in modern C++ -- just use a std::vector <std::string>.
int main()
{
std::vector <std::string> myStrings;
myStrings.push_back ("hello");
myStrings.push_back ("goodbye");
}
This achieves all your mentioned goals of being RAII and no need to new or delete anything. It also integrates very nicely with other Standard Library facilities, such as find.
I did say "obviate most needs," emphasis mine. There is still occasional need to go old-school. I won't discuss them here since if you actually need it you already know. Which is to say, if you don't know you probably don't need it.
All that being said, std::unique_ptr does support managing C-style arrays with special syntax:
std::unique_ptr <unsigned []> myArray (new unsigned [256]);
the array managed by myArray above will be properly deleted with delete [] at destruction time.
Since there is no unique_ptr analogue to shared_ptr's make_shared, you will either have to use new to actually construct the array, or provide your own (or someone else's) implementation of make_unique
Sidebar: make_unique will be added to C++14.
1 " you should be using std::vector<> unless you have an understanding of the other containers and a compelling reason not to"
This isn't just my opinion. It's also the general (unofficial) opinion of StackOverflow as a whole, C++'s creator Bjarne Stroustup, and the C++ Standard itself (23.1.1).
std::vector<T> is an RAII array type. From the additional information you've given std::vector<string> is appropriate for your use.
string results[] = new string[source.size()]
Just as an aside about arrays, this syntax isn't correct for C++. People teaching C and C++ often teach that arrays and pointers are the same thing, but this is not true and the syntax above shows one of the ways they differ.
The actual relationship between arrays and pointers is
Arrays and pointers are distinct types
In many contexts an implicit conversion from an array to pointer is applied. The conversion results in the address of the array's first element.
pointer arithmetic is defined such that if a pointer points to an element in an array then you can get pointers to other elements of the array by adding and subtracting to the pointer value.
In a some contexts writing an array type will result in a pointer type. In particular, function parameters declared to be of array types are adjusted to be of pointer type. E.g. void foo(int[10]); is effectively identical to void foo(int*);.
So the code you show is declaring an array and initializing it with a pointer. This will result in an error because there's no conversion from pointers to arrays.
Generally you should avoid raw arrays in C++; Arrays just have too many weird rules, such as the weird function parameter rule described above, the rules about when exactly the implicit conversion is performed, prohibitions on assignment and returning arrays from functions, etc. When starting out it's probably best to just stick with the std::array template for arrays with a size known at compile time and the std::vector template for arrays with a size not known at compile time.
You can use std::vector<string> and push_back() each result string in to the vector. You don't have to use new unless you want to avoid vectors and manage memory by yourself
I think a simple template would do the trick in the general case:
template<class T>
class HeapArray {
T* ptr = nullptr;
public:
HeapArray(int size) { ptr = new T[size]; }
~HeapArray() { delete [] ptr; }
operator T*() { return ptr; }
};
You use it as:
HeapArray<std::string> results(source.size());
results[i] = "how cool is this";
basically the HeapArray object is automatically cast'd to its member pointer.
Is the name of a vector simply a pointer, just like a vanilla C array?
Thus, I could send the address to a single piece of non-vector data (a pointer, in other words) to a function argument that expects a vector since a vector is also a pointer.
For example, a function that is declared as this:
void RenderingEngine::Render(const vector<Visual>& visuals) const{
Could be called like this:
Visual visual; // is NOT a vector
//do stuff with visual
m_renderingEngine->Render(&visual);
Makes sense and is valid, legal C++?
This example code is from an O'Reilly C++ book, so I guess it is an error in the book.
Is the name of a vector simply a pointer, just like a vanilla C array?
No. It's a fully-formed class.*
* What's more, a vanilla C array is not a pointer either (it just get turns into one in most situations).
No. That doesn't make sense. There is no implicit conversion from T* to std::vector<T>.
But in C++11, you can do something which is very close1 to what you're doing. You could create the vector on the fly while passing the argument as:
m_renderingEngine->Render( {visual} ); //note the curly braces!
With that you create a vector object out of the expression {visual} which then gets passed to the function.
1. very close in the sense that you just have to type one more character to make your code work. Instead of typying &, just type {, and one more } at the end. That is it. Life is so easy with C++11.
No, it isn't, which is rather fortunate because the behaviour of C arrays is abominable. If you find yourself looking for it, I would suggest instead looking for some new learning material w.r.t. C++.
The other answers are correct, but I'd like to add that it works the other way around:
void RenderingEngine::Render(Visual *visuals, size_t n_visuals);
Can be called like this:
vector<Visual> visuals;
m_renderingEngine->Render(&visuals[0], visuals.size());
You just take the address of the first element and pass it as if it was an array. This works because the elements of a vector are laid out sequentially in memory. (As pointed out in the comments, shouldn't use this in new code, of course. It's safer and easier to define you method to take a vector. However, if you already have a legacy function that takes a pointer, this allows you to use vectors in your own code.)
The reason it works this way around, but not the way in your question (pass a pointer, to a function that takes a vector), is that in your case it can't determine the size of the array at runtime. But it has to know the size to construct the vector:
// (wrong code)
// Passing one element:
Visual visual;
m_renderingEngine->Render(&visual);
// Passing two elements, how does Render know that
// there are two elements at that address?
Visual[2] visuals;
m_renderingEngine->Render(&visuals[0]);
As Nawaz pointed out, you can do something similar in C++11:
Visual visual;
m_renderingEngine->Render( {visual} ); // C++11
You can also put more elements in the {}. This only works because the compiler can tell at compile-time how many elements there will be. It's just syntactic sugar for:
vector<Visual> myVec = {visual}; // C++11
m_renderingEngine->Render(myVec);
which in turn works like the classic:
vector<Visual> myVec;
myVec.push_back(visual);
m_renderingEngine->Render(myVec);
(although the C++11 version might be slightly optimized, I don't know for sure).
What's the real benefit of using pointers to functions instead of those functions itself? Does it make execution faster ? Or does it provide convenience when it's passed to another function?
It enables you to "select" a component of your business logic around at run time -- contrast this with hardcoding the function names, which limits you to choosing which function to use at compile time.
There are situations where you must use a pointer to function, there is no other way. For example, to implement a callback function, specifying comparator function(the last parameter in sorting routines).
EDIT: As specified in the comment, this is about C. Function pointer came from C.
Function pointers are how you store functions in variables and pass them into other functions. There are no "advantages" over "regular functions", they are completely different things and trying to compare them doesn't make sense. It's like asking "which is better, variables or if statements?"
Function pointers provide a functionality that would otherwise be unavailable.
In fact passing a pointer of a function is a little bit slower than calling the function itself. But the difference is so little that it can hardly ever have any effect.
As Jon said, it brings more flexibility in some cases, when you can pass the function from one part of your programm to another.
function pointers are used in many situations where you are not sure which function to call exactly. Lets take an example. you want to sort an array. For that you want to write a generic sort function . Now this sorting function needs to compare the array elements. But since array can have any elements (int, floats, strings, user defined types etc), how this sort function can compare the elements. So, in this case, you can pass the ordering-determining function as an argument to this sort function and based on that it can sort the array. Also, it is usefull in another way as well. Lets say you want to sort an array of string (a string of numbers). you may want to sort it numerrically or in alphabatically.
In this case, when you want to sort nnumerically, you can pass compare function which compares based on the value of string converted to int. and so on...
I am trying to define
Vertex[] total_vertices = new Vertex[no_vertice];
in C++. But when compiling I get this:
:568:8: error: expected unqualified-id before ‘[’ token
I need to declare an array of Vertices of size "no_vertice", and then use its "Length" method to get its size. Why is it not working?
In C++, the [] only goes after the variable name, not after the type (unlike Java or C#).
But that wouldn't work anyway, because you can't assign a pointer-to-first-element-of-an-array (returned by new) to an array. You need to use a pointer:
Vertex* total_vertices = new Vertex[no_vertice];
And make sure to delete[] it after you're done using it.
You say you need to use it's Length method, which has two problems:
Arrays don't have methods like they do in java; they're just blocks of memory in C++. If you want to use an array-like structure that has member functions, check out std::vector
You wouldn't need the Length method of an array even if they did have one (which they don't) because you already have the size in the variable no_vertice.
C++ arrays don't have length methods. You need to look at std::vector.
The right way to do it is.
Vertex *total_vertices = new Vertex[no_vertice];
However, in C++ builtin arrays have no Length method. They have no method at all since they are not classes. The "length" of it would be no_vertice.
You seem to be talking Java or C#...
You want
std::vector<Vertex> total_vertices(no_vertice);
and then use its size() method to get the size.
It's best to avoid using new directly unless there's no alternative - it's very easy to lose track of the object's ownership and end up with a memory leak.
You should probably do something like
boost::shared_array total_vertices( new Vertex[no_vertices] );
or
boost::scoped_array total_vertices( new Vertex[no_vertices] );
that way you don't have to worry about cleaning up after yourself and leaking memory.
http://www.boost.org
In C++, always use a vector rather than an array if a vector can do what you want. Because a vector provides an easy way and some useful methods (such as the size() you want). The most important thing is that a vector is safer than an array when you subscribe an element in it (vector has a end() method to make sure you can't access out of the range of it). So I think you should write this:
#include <vector>
std::vector<Vertex> total_vertices(no_vertice); //vector is a container so you should declare it with a specified type.
You can get more information about vector in the C++ reference of vector.