return a std::vector in c++ - c++

EDIT
*Please , upvote this topic because I cant ask anymore question in this forum.
Programming is my life and I'm just stuck because of an automated banning . Thank you ( or I need the help of a moderator to solve this problem *
I'm a beginner programmer in c++ and I want to basically return a std::vector
When I debug my code I get function call missing argument list . Here is my simple code
Thanks for your help
#include "stdafx.h"
#include <vector>
#include <iostream>
static std::vector<int> returnStaticVector();
static std::vector<int> returnStaticVector(){
std::vector<int> vectorInt = std::vector<int>();
vectorInt.push_back(0);
return vectorInt;
}
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<int> a = std::vector<int>();
a = returnStaticVector(); // Compile , but error when I try to access to the size of the std::vector
//int size = a.size; //error C3867: 'std::vector<int,std::allocator<_Ty>>::size': function call missing argument list; use '&std::vector<int,std::allocator<_Ty>>::size' to create a pointer to member
//int size = &a.size; // & Illegal operation
//int& size = a.size; //error C3867: 'std::vector<int,std::allocator<_Ty>>::size': function call missing argument list; use '&std::vector<int,std::allocator<_Ty>>::size' to create a pointer to member
int* size = a.size; //error C3867: 'std::vector<int,std::allocator<_Ty>>::size': function call missing argument list; use '&std::vector<int,std::allocator<_Ty>>::size' to create a pointer to member
return 0;
}

In std::vector size is a member function, not a member variable. You use it like this:
int size = a.size();
If you don't have the parentheses, it is a syntax error.
Incidentally, another thing you can do to simplify your code is declare vectors like this:
std::vector<int> a;
Or in C++11
std::vector<int> a{};
Both of these will default-construct the vector -- this works for any class type.
Doing it this way,
std::vector<int> a = std::vector<int>();
is not as good because it is longer and makes you type things twice, and also it copy initializes it rather than default constructing it, which is slightly different and may be less efficient.

First things first -- The real compile problem in your code is because you have used a.size instead of a.size(). Try changing that and the code should compile successfully.
Apart from that, I don't think it's a good idea to return a vector like what you have done. Try passing vectors using reference from the calling function. That is much better design.
If you are still thinking about return by value think in terms of Copy elision which is an optimization implemented by compilers to prevent unnecessary copies in many cases. It makes returning by value or pass-by-value feasible in many cases.
Read more about copy elisions here :-
http://en.cppreference.com/w/cpp/language/copy_elision
What are copy elision and return value optimization?

Related

Problem with passing list pointer to a function

In my program I have a list which is a pointer list<COffenceUnit*>* m_attack = nullptr; I initialize this list like that: m_attack = new list<COffenceUnit*>(); in the constructor. At some point in the code I want to send this list to another constructor as a reference. This is the constructor that receives the list:
GameMap::GameMap(const std::list<CDefenceUnit*>* &defenseUnits, const std::list<COffenceUnit*>* &offenseUnits)
{
mGameMap = new int* [GRID_SIZE];
for (int i = 0; i < GRID_SIZE; ++i)
mGameMap[i] = new int[GRID_SIZE];
updateMap(defenseUnits, offenseUnits);
}
However the compiler throws an error that says:
Error C2664 'GameMap::GameMap(const GameMap &)': cannot convert argument 1 from
'std::list<CDefenceUnit *,std::allocator<_Ty>> **' to 'const std::list<CDefenceUnit *,std::allocator<_Ty>> *&'
I can't figure out what am I doing wrong here.
You're trying to call the function with a pointer-to-pointer-to-list (std::list<...>**), but the function expects a pointer-to-list (std::list<...>*), so the conversion fails.
Dereference the argument to remove one level of pointer. For example if you had GameMap(defenseUnits), then change that to GameMap(*defenseUnits).
Also you should almost never new std containers, so to initialize your m_attack, it's recommended to do it without new (i.e. without dynamic allocation), like so:
list<COffenceUnit*> m_attack;
Then you also don't need to do m_attack = list<COffenceUnit*>(); later, because the list is already default initialized by the list's constructor.
This also helps you avoid multiple levels of pointers, such as in std::list<...>**.
Also you probably want std::vector instead of std::list, the latter is rarely a better choice.

Const vector query in C++

#include < vector >
using namespace std;
class Rclass
{
public:
vector<int> ir0T;
vector<int> ir1T;
private:
int f();
}
int Rclass::f()
{
ir0T.clear();
ir1T.clear();
ir0T.push_back(1);
ir1T.push_back(2);
}
this throws error
"Rclass.cpp:90: error: member function 'clear' not viable: 'this' argument has type 'const vector', but function is not marked const
ir0T.clear();
^~~~"
Rclass.cpp:91: error: member function 'clear' not viable: 'this' argument has type 'const vector', but function is not marked const
ir1T.clear();"
why?
^~~~
I tried adding "const vector ir0T;"
You cannot set the matrix member variable to a local varable created in a local member function - the local variable will be destroyed when the function ends and then the matrix member variable won't be pointing to anything. So instead, if you insist on using a raw pointer, use calloc() because it allocates the memory like malloc and then it sets it all to zero. The main problem with this is that then you need a copy constructor, assignment operator and destructor - That's not the way to go if you can help it. It would be better to use a std::vector<std::vector<int>> because all the dynamic allocation and deallocation is hidden from you. Plus you can reserve the size if you know it ahead of time. How to initializ the "vector"-ized version to zero can be seen here: Initializing a two dimensional std::vector
#include <vector>
class CS
{
private:
std::vector<std::vector<int> > Rightalpha;
public:
void CreateMtrx(int a, int b)
{
// Defaults to zero initial value
Rightalpha = std::vector<std::vector<int> >(a, std::vector<int>(b));
}
};
int main()
{
CS cs;
cs.CreateMtrx(4,4);
return 0;
};
A better alternative if it is fixed and you know ahead of time how big the matrix is: you can just use a plain array directly as a member variable instead of using a pointers to dynamically allocated memory. If the matrix is small (like 4x4) this will give you cache locality and a performance improvement. Plus if you are using c++11 you can clear the array at the declaration and you don't need a CreateMatrix() member variable at all - something like this:
class CS
{
private:
int Rightalpha[4][4] = {};
};
int main()
{
CS cs;
return 0;
};
Or like one of the comments suggested you could use std::array instead of a plain array, if you want a nice STL-like interface to the array. There are some advantages listed here: Replace fixed size arrays with std::array?
Firstly a few fundamentals.
When CreateMtrx() returns Rightalpha will become invalid as a will destruct.
And I would recommend using lower camel case naming for variables and upper camel case for types. i.e. rightAlpha instead of Rightalpha, to avoid confusion with types.
As for your actual question you can initialise a 2D array with a nested loop:
for(unsigned int i = 0; i < 4; i++)
{
for(unsigned int j = 0; j < 4; j++)
{
rightAlpha[i][j] = 0;
}
}
Finally, when asking for help 'craps up' is not conducive to constructive answers. It is important to be clear on what your expected behaviour is and what results you are actually seeing.
If Rightalpha is a data member of your class it doesn't need to be an int**. You probably just want it to be an int[4][4] and skip using a local variable 'a' in your create function.
If you really want it to be a pointer, just make it an int*, and use it with 2D-array syntax. Instead of: int a[4][4]; Do: int* a = new [4*4];
I see from the comment that you can't change the type of Rightalpha. You will then need to do manual memory management. You will need to initialize you int** with the new operator.
You will need to allocate each array in the 2D array.
rightAlpha = new int*[4];
for (int i = 0 ; i < 4 ; i++) {
rightAlpha[i] = new int[4];
}
You can read more about initialisation of a multi-dimentional arrays here:
How do I declare a 2d array in C++ using new?
Even if that works, you will need to free and manage memory and deal carefully with all the pitfalls of manual memory management. That's why I strongly suggest to use a std::vector<int>:
struct CS {
createMatrix() {
rightAlpha = std::vector<int>(4*4);
}
private:
std::vector<int> rightAlpha;
With this solution, you don't need to worry about memory stuff as the std::vector will do it for you.
If you need matrix semantics, you can add a function that returns the right element according to a j i position.
int operator()(int i, int j) const {
return rightAlpha[j+4*i];
}
It may be used like this:
CS myCs;
myCs(3, 2);

C++ - How do I put a static array inside my array?

I apologize for the total noob question, but I just cannot find an answer. I googled, searched here, searched C++ array documentation, and some C++ array tutorials.
The question is simple. Why does
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
short pixelarray[3][3] = {{1,1,1},{0,0,0},{-1,-1,-1}};
... //do stuff. Imagine a loop here, and BIG array - I'm just simplifying it for StackOverflow
pixelarray = {{1,0,-1},{1,0,-1},{1,0,-1}};
return 0;
}
result in an error?
1>arraytest.cpp(11): error C2059: syntax error : '{'
How do I put a static array inside my array? I realize I could set each item individually, but there has to be a better way.
Built-in arrays in C++ have their problems, and not being assignable does make them rather inflexible. I'd stick with std::array, a C++11 container that emulates a better style of array, which allows a somewhat similar syntax to what you're looking for:
std::array<int, 3> arr{{1, 2, 3}};
std::array<int, 3>{{4, 5, 6}}.swap(arr);
//now arr is {4, 5, 6}
Here's a full sample. The trick is to use the initializer list on a newly-constructed array and then swap that with yours. I believe that the next C++ update is going to remove the need for the double braces as well, which makes it an even closer match to familiar syntax.
Initializer lists can be used just for initialization :)
Like when you declare your variable:
short pixelarray[3][3] = {{1,1,1},{0,0,0},{-1,-1,-1}}; // this is ok
You have to remove this:
pixelarray = {{1,0,-1},{1,0,-1},{1,0,-1}};
And assign new values manually (i.e. pixelarray[x][y] = or with a memcpy(pixelarray, <some other array>, sizeof(pixelarray)))
If you don't want to assign each individual element manually, you can do this:
short pixelarray2[3][3] = {{1,0,-1},{1,0,-1},{1,0,-1}};
memcpy(pixelarray, pixelarray2, sizeof(pixelarray));
As #Nick points out: initializer lists are not for assignment.
Arrays are not assignable, so the short answer is that you can't do exactly what you're asking for. The most direct way to do something similar enough for most purposes is probably a 2D array class that acts as a wrapper around a std::vector, on the order of the one I posted in a previous answer.
If you insist on staying with C-style arrays, one possibility would be to use a pointer:
int main() {
typedef short array[3];
array pixelarray0[3] = {{1,1,1},{0,0,0},{-1,-1,-1}};
array pixelarray1[3] = {{1,0,-1},{1,0,-1},{1,0,-1}};
array *pixelarray = pixelarray0;
// when needed:
pixelarray = pixelarray1;
}
Taking this question from a straight C context, you can have different constant arrays and just copy them with memcpy:
typedef short TArray[3][3];
const TArray a1 = {{1,1,1},{0,0,0},{-1,-1,-1}};
const TArray a2 = {{1,0,-1},{1,0,-1},{1,0,-1}};
// ...
TArray a;
memcpy( a, a2, sizeof(TArray));
Or you could exploit C99 struct copying, but I'd consider this a dangerous hack because the structure might be padded to be larger than the array, or have a different alignment.
typedef struct {
TArray arr;
} TDummyArray;
// ...
TArray a;
*(TDummyArray*)a = *(TDummyArray*)a2;
Once you have declared your array there is no way to use the assignment operator to reassign the entire content of the array.
So to change the contents or your array after this:
short pixelarray[3][3] = {{1,1,1},{0,0,0},{-1,-1,-1}};
You need to either loop through the array and manually change each value, or you something like std::memcpy to copy your new values over.
But you should really not be using an array in the first place, use some fromthing the std collections library instead like std::array or std::vector. Only use arrays if you have a really really good reason why you can't use a collection.

C++: Return multiple NEW arrays

I think this is an easy issue, but it's driving me crazy: I want to return multiple arrays from one method, for which the calling method does not know their size in advance. So I have to create those Arrays inside the method (in contrast to just filling them) and I am not able to return them using return.
So what I would want is a method signature like this:
void giveMeArray(int[] *anArray)
Method signature has only one parameter to simplify the examples, please assume I could also have a signature like
void giveMeArrays(int[] *anArray, float[] *anotherArray)
Inside that method giveMeArray I would construct the array with
*anArray = new int[5];
and I would call that method using
int[] result;
giveMeArray(&result);
However, all this (starting with the method signature) is at least syntactically wrong. Please excuse that I don't have the compiler errors at hand by now, I'm pretty sure some of you will know what's wrong.
EDIT I know that std::vector would be the best (meaning cleanest) approach. However, folks, that wasn't the question.
Return a single vector (this is C++ afterall)
void giveMeArray(std::vector<int>& anArray)
{
anArray = std::vecotr<int>(5);
}
Return a vector of vectors:
void giveMeArray(std::vector<std::vector<int> >& anArray)
void giveMeArray(int **anArray);
int *result;
giveMeArray(&result);
std::vector<int> giveMeArray() {
std::vector<int> ret;
ret.resize(5);
return ret;
}
Nice resource cleanup, bounds checking in debug modes, etc. Good for all the family.
Consider wrapping the arrays in a class or struct.
struct Arrays {
int *ints;
int intCount;
double *doubles;
int doubleCount;
};
Arrays giveMeArrays() {
Arrays arrays;
arrays.ints = new int[10];
arrays.intCount = 10;
arrays.doubles = new double[20];
arrays.doubleCount = 20;
return arrays;
}
An alternative is to use a std::pair<> or a std::tuple<>, but in my experience any use of those eventually becomes a named type. The fact that they are all part of the result of your function suggests they may have enough coherence to be an object. Having a user-defined type makes it easier to pass the data around, and so to refactor code. You may even find that giveMeArrays() becomes a member function of this object.
Replacing ints/intCount with std::vector<int> would be better, if possible. If not, you may want to give Arrays more responsibility for memory management, disable copying while allowing moving, and so forth.

Vector of object pointers, initialisation

I'm not very experienced with C++ yet, so bear with me if this is basic stuff.
I have some code like that below. L is an abstract class (it has a number of pure virtual functions), and A, B and C are regular classes all derived from L. There may be any number of these, and they are all different.
int main() {
// ...
std::vector<L*> ls(3) ;
ls[0] = new A ;
ls[1] = new B ;
ls[2] = new C ;
int i ;
for (i = 0 ; i < ls.size() ; i++) {
if (ls[i]->h()) {
// ...
}
}
// ...
}
It works, but there really has to be a better way to initialise that vector. Right?
The vector is not supposed to change after it has been first initialised. I figure I can't make it const, however, because the various objects may themselves change internally. I picked a vector over a regular array because I don't want to manually keep track of its length (that proved error prone).
Ideally I'd like to pull the definition and initialisation of the vector out of main and preferably into a separate file that I can then #include. When I try that the compiler complains that it "expected constructor, destructor, or type conversion before ‘=’ token". All the classes A, B and C have default constructors.
Also, I was under the impression that I have to manually delete anything created using new, but it won't delete ls with either delete or delete[]. If I try delete ls; the compiler complains that "type ‘class std::vector<L*, std::allocator<L*> >’ argument given to ‘delete’, expected pointer".
Is the above even safe or does it cause some memory problems?
but there really has to be a better way to initialise that vector. Right?
I don't think so, at least not without C++0x. Which way would you prefer? Your initialization code is completely fine.
I figure I can't make it const, however, because the various objects may themselves change internally.
You can still make the vector itself const, only its member type cannot be a pointer to const then.
I picked a vector over a regular array because I don't want to manually keep track of its length (that proved error prone).
You don't have to keep track of the length in constant arrays:
L* ls[] = { new A, new B, new C };
// with <boost/range/size.hpp>
std::size_t num = boost::size(ls);
// without Boost, more error-prone
// std::size_t num = sizeof ls / sizeof ls[0];
And often you don't need the size anyway, e.g. with Boost.Range.
Ideally I'd like to pull the definition and initialisation of the vector out of main and preferably into a separate file that I can then #include.
That would violate the one-definition rule. You can put the declaration into a header file, but the definition has to go into a source file.
Also, I was under the impression that I have to manually delete anything created using new, but it won't delete ls with either delete or delete[].
Your impression is correct, but you haven't created ls with new, only its elements. After using the vectors, you have to delete each of its elements, but not the vector itself.
The recommended alternative to STL containers holding polymorphic pointers is the Boost pointer container library.
You do indeed have to use delete on the objects you created. You are calling delete on the vector not the objects. Something like:
for(size_t i = 0; i < ls.size(); i++){
delete ls[i];
}
For your construction issue you could wrap them into a function and put that function in it's own header file. You would have to make sure to include all of the relevant classes header files as well.
void init_vector(std::vector<LS*> & v){
ls[0] = new A ;
ls[1] = new B ;
ls[2] = new C ;
}
If C++11 is acceptable, you might be better off with an std::array instead of std::vector:
std::array<L *, 3> = {new A(), new B(), new C()};
Since you know the size at compile time, I suggest using an array instead of a vector. Using the class template array instead of a C-style array gives you the benefit of a standard container interface, just like a vector. That is, you can call size() on the array and obtain iterators and so on.
And to make sure you don't forget to delete the objects, I suggest using smart pointers:
#include <boost/array.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
boost::array<boost::shared_ptr<L>, 3> ls = { {
boost::make_shared<A>(),
boost::make_shared<B>(),
boost::make_shared<C>(),
} };
Modern compilers ship their own versions of array and shared_ptr in the standard library:
#include <array>
#include <memory>
std::array<std::shared_ptr<L>, 3> ls = { {
std::make_shared<A>(),
std::make_shared<B>(),
std::make_shared<C>(),
} };
Note that the outermost braces are technically not needed, but leaving them out might produce compiler warnings, at least that's what happens on my compiler.
Ideally I'd like to pull the definition and initialization of the vector out of main and preferably into a separate file that I can then #include
In that case, you need a header file with a declaration and an implementation file with a definition of ls:
// file ls.h
#ifndef LS_H
#define LS_H
#include <boost/array.hpp>
#include <boost/shared_ptr.hpp>
extern boost::array<boost::shared_ptr<L>, 3> ls;
#endif
// file ls.cpp
#include "ls.h"
#include <boost/make_shared.hpp>
boost::array<boost::shared_ptr<L>, 3> ls = { {
boost::make_shared<A>(),
boost::make_shared<B>(),
boost::make_shared<C>(),
} };