This seems like a really basic thing to do, but anyway I couldn't manage to find a solution to it so far, because I always find only questions that are asking how to check if the vector is actually empty, which is not what I want to check for.
Consider this code example:
#include <iostream>
#include <vector>
using namespace std;
struct Atom {
int x,y;
int pol;
};
int main() {
vector<vector<Atom>> vec=vector<vector<Atom>>(5,vector<Atom>(5));
cout<<(vec[0][0]==nullptr); // this line doesn't compile, because the vector doesn't hold pointers.
return 0;
}
I'm trying to declare a vector of vectors of objects of a custom type. At the beginning of the Programm I will initialise the vector so that it has a specific size, but without assigning an actual object to it. Now I want to be able to check if I already assigned an object to a specific position of the vector. I would've liked to use something like vec==nullptr but this doesn't work, because the objects in the vector aren't pointers. Unfortunately I can't just change the structs standard constructor to put some indicator value that I can check for like Atom.pol==-2, because the class is created by ROS messages. Any other suggestions on how to check if I already assigned an object?
EDIT: pol will always be either -1 or 1 after I assigned an object. So is it safe to check Atom.pol==0? When I tried to do this on ideone.com it always worked, but I assume that it's not guaranteed to be 0, right?!
There is no way to check whether an object has been initialised. That said, elements of std::vector are always initialised, so there is never a need to check either.
It seems that you want to represent an "unassigned" object. The standard library has a template for you: std::optional. If you create a vector optional objects, those objects, when value-initialized, will be in "unassigned" state.
EDIT: pol will always be either -1 or 1 after I assigned an object. So is it safe to check Atom.pol==0?
Yes, that would be safe, since the constructor that you use initialises the elments using a value initialised argument.
If you can assume that some states of the object are "not valid", then you don't necessarily need to use std::optional. If the value initialised state is such invalid state, then you don't need to add a default constructor to the class either. Just like a value initialised pointer compares equal to nullptr, so too the integer members of the value initialised Atom compare equal to 0.
but I assume that it's not guaranteed to be 0, right?!
It is guaranteed to be 0.
The solution to use pol == 0 should be fine, provided that pol == 0 is in fact not a normal state for that object to be in and that you don't try it with an uninitialized instance.
The std::vector constructor you are using guaranties that the new elements are default inserted. If you are using the default allocator (which you are) then that performs value initialization of those new elements. Since Atom is a class type with a default constructor that is neither user-provided nor deleted, then your instance of Atom are zero initialized. That means each of Atom's members' value is initialized to zero.
Beware that this is something std::vector does. You need your Atoms to be initialized to zero for this approach to work. If you tried the following, it would be undefined behavior. The Atom members are not initialized, much less guaranteed to be zero :
int main()
{
Atom a;
std::cout << (a.pol == 0); // <- Not okay
}
You can force value initialization by adding {} though :
int main()
{
Atom a{};
std::cout << (a.pol == 0); // <- Okay now
}
Edit : Accidentally used the same code sample for both examples.
One way to do this is to change the signature of vec to,
vector<vector<Atom*>> vec=vector<vector<Atom*>>(5,vector<Atom*>(5));
Then you can do the null ptr check to see if a given element has been initialized. This does add some complexity though, as you have to handle the memory allocation yourself.
If you want to initialize the members of Atom to specific values and check if they are initialized, you can do this.
vector<vector<Atom>> vec=vector<vector<Atom>>(5,vector<Atom>(5, {1, 2, 3}));
This initializes x, y, pol to 1, 2 and 3 respectively.
Minimal Example:
int main() {
using std::cout;
using std::vector;
vector<vector<Atom>> vec=vector<vector<Atom>>(5,vector<Atom>(5, {1, 2, 3}));
cout<<((vec[0][0]).x == 1) << "\n";
cout<<((vec[0][0]).y == 2) << "\n";
cout<<((vec[0][0]).pol == 3) << "\n";
cout<<((vec[0][0]).x == -1) << "\n";
cout<<((vec[0][0]).y == -1) << "\n";
cout<<((vec[0][0]).pol == -1) << "\n";
return 0;
}
See Demo
Related
I run the following codes in http://cpp.sh/.
The outputs show that name1.size()=2, but name1[100]=10;
// Example program
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<vector<int>> name;
vector <int> name1;
name1.push_back(1);
name1.push_back(3);
vector <int> name2;
name2.push_back(4);
name.push_back(name1);
name.push_back(name2);
name1[100]=10;
cout<<name1.size()<<endl;
cout<<name1[100];
}
The short answer is that you are invoking undefined behavior, so you won't find any further specification of what must happen in the standard.
The long answer is that C++ is an unsafe language and doesn't guarantee any type of deterministic error for various invalid operations, including accessing a vector out of bounds using operator[]. Instead, it uses the broad brush of undefined behavior which basically allows anything at all to happen: the idea being that by allowing the user the flexibility to avoid checks which they know are redundant, good performance can be achieved for well-behaved code.
If you want the vector to check that you aren't accessing an out-of-bounds index, no problem - just use the vector::at() which does exactly that, and throws std::out_of_range for invalid accesses.
As for why your particular code is (apparently) returning a value, note that a typical1 implementation of operator[] will just access the underlying storage directly, meaning that at the assembly level you will access whatever is 100 * sizeof(int) bytes from the start of the storage underlying the vector. That's usually going to be something random on the heap (since the storage is usually allocated on the heap), but it may also be an inaccessible address, resulting in an access violation.
1 Some compilers such as MSVC will provide more error checking in "debug" modes, which might cause operator[] to call vector.at() instead, which does do range checking and has defined behavior, and at least a few other compilers/standard libraries seem to be jumping on board with that idea.
Try this code here.
You declared:
vector <int> name1; // An empty vector. name1.size = 0 here.
Once you push_back the two values.
name1.push_back(1);
name1.push_back(3); // name1.size = 2, Index starts at 0, so
// name[0] = 1 and name[1] = 2
So the value for:
name1[100] = undefined (garbage). // You never initialised this value, so it yields unexpected behaviour.
An alternative for this is to use a default initialiser for an int vector and declare it like this:
vector <int> name1(101);
Here:
name1[100] = 0 // Because you defined it in the vector constructor to initialise 100 default values.
name1[0] = 0 // This is the first value of the now initialised vector.
name1[69] = 0 // This is the 70th value of the initialised vector.
name[101] = undefined // Again, this is undefined (garbage). You defined a vector of size n = 101, so that means the vector's range is [0,100]. 0 index counts and the last value is n - 1 (101 - 1 = 100). Index 101 is undefined.
I'm doing my homework (and learn how C++ works).
My task is:
Define some class with field...(never mind)
create an vector and array from these object and iterate it! (listing, average by field,etc).
Now it's correctly works with vector, but array doesnot work:
static Cipo* cipok; // object array
static int cep = 0; // endpoint index
static int ccap = 0; // array size
Default assignmet opearator for Cipo:
public: Cipo& operator=(const Cipo &c)
{
return ((Cipo&)c);
}
Initalization:
cipok = (Cipo*) malloc(sizeof(Cipo*)*100); // new Cipo[num] doesn't work..
ccap = 100;
Test code:
for (int i = 0; i < 5; i++)
{
Cipo c(43.5, "str", 12670, false, false);
std::cout << c.ar <<" ";
cipok[cep] = c;
std::cout << cipok[cep].ar << " ";
cep++;
}
And the result:
12670 0 12670 0 12670 0 12670 0 12670 0
But objects not "disappeared" if I use vector, push_back() the objects and read from the vector with direct indexing (or with iterators). Why do they exhibit this behaviour?
You immediate problem is likely caused by whacky implementation of operator = that does absolutely nothing. I'd recommend step through the code in debugger to see it. operator = (and copy constructor) should properly copy values into destination object.
There are many other issues with the code - your naming convention is ... interesting, you seem to try to cast whatever you have to whatever result is required for code to compile without reasoning what should actually be done. malloc in C++ code is very rarely needed...
I think the general problem is, I'm programming always in java (but now in university i must prog. in C/C++, naming conventions, like in java and in hungarian the Cipő is meaning Shoe). And in Java there is no pointers, and all object always acces by reference, but looks like (as i tested ) if i create a new object array the C++ will not allocate only 100 pointer which points to the object (where the object data starts), it allocated 100*sizeof(object) and for this place i can add data trougth assing operator.
it's my teory true?
So i tried to manage Object acces like in java.
Why copy the Object if itself alredy exist? (I don't like to "clone" objects).
I am an intermediate java programmer and I am used to relaying on the null value in java for cheking if objets are initialized with some reference to instanced object in memory. I want to do something similar in c++ but I do not have a clear idea about how I can achieve it. I want to initialize a user array - user is a class I have defined - so I can check if the actual position in the array does contain an object or it is free.
I have tried to use the null definition in c++ but found out that it is simply a "-1" int value and I could not use it properly. So basically I need something to distinguish between a free position in my array and an ocuppied one.
Additionally I might be interested in having an extra value to distinguish a position that contained a removed user, since I am planning to just mark the desired position with a special mark as a freed position when it comes to the method that remove a user from the array.
For the curious ones, I am implementing a simple hash set and the remove method in my class just mark the position of the element to remove instead of doing some restruction.
First of all null definition is not -1 but 0. Assuming you have something like
class User
{
};
User RemovedClass;
you can have something like this
User *arr[3];
arr[0] = new User();
arr[1] = 0;
arr[2] = &RemovedClass;
Here 0 is a new User, 1 is java null equivalent , 2 is marker for deleted class.
EDIT
Typically when you see User array in java you will have to map it to a User* array in C++.
After these operations.
User a;
User b;
a = b;
in java a and b will refer to the same User. In C++ such code will yield to a and b referring to two different User objects.
I think there are some concept you need to understand.
Unlike Java, when you are creating an N-element array of User, it is NOT an array of reference. It is really a piece of memory containing actual N user, which is already created and initialized (i.e. constructor already run). (Well, there are more advanced topics like placement-new but I think it is not really what you are looking for yet)
So it is somehow contradicting if you said you have an "array of User" and want to keep track if certain position is initialized.
Unless:
You are not creating array of User, but Array of "Pointer to User" (or other reference like auto_ptr). By such way, it is meaningful to say certain element is "null"; or
Your "initialize" do not mean creating an object instance, but an explicit initialization action (like executing an init() method of an User instance). By such way, it is meaningful to say certain element is "not initialized".
(First of all, as you are writing C++, I shall recommend you to use std::vector, not array. However I am using array in this answer, as to stick close to your question)
For case 1, it is strict forward, simply use NULL (avoid using 0, because, although NULL is defined as 0 in most system, using NULL actually makes the code more readable and more portable):
User* user[10] = {NULL}; // array of 10 pointer-to-User
user[0] = new User(...);
assert (user[0] != NULL);
assert (user[1] == NULL);
For case 2, you have many other choice, like keeping another array of boolean to keep the "initialized" flag, or have a wrapper over User for such extra flag, or simply add such flag into your User class, etc.
e.g.
User user[10]; // 10 element of User, which all of them is already created
//assume you have extra flag in User
user[0].init(...); // explicity do some init work on user[0]
//......
if (! user[5].isInitialized()) {
user[5].init(...);
}
(honestly I think case 2 is not really what you are looking for)
I use boost::optional:
boost::optional<int> a;
if (!a) { std::cout << "no a!"; }
a = 5;
if (a) { std::cout << "a = " << *a; }
a = boost::none;
if (!a) { std::cout << "no a!"; }
I am confused on a couple homework questions I have...
Can you return multiple data items from a function by using return()? Can a function only return one value, unless it is a pointer to an array?
I believe that the answer is that a function can return multiple data items by returning a structure. Then, returning a pointer to an array is not the only way - if that is a way?
But there seems to be a lot of discussion on this topic and so I want to make sure I have at least the basic idea correct: You can return multiple data items using a structure but using pointer (I don't understand this) will use memory more efficiently. Is this correct?
With C++0x/C++11 you can use this:
#include <string>
#include <iostream>
#include <tuple>
using namespace std;
tuple<int, unsigned, string, int> getValues()
{
return tuple<int, unsigned, string, int>(1, 2, "3", 4);
}
int main()
{
int a;
unsigned b;
string c;
int d;
tie(a, b, c, d) = getValues();
cout << a << ", " << b << ", " << c << ", " << d << endl;
return 0;
}
Compile it with
g++ tuple_test.cpp -std=c++0x -o tuple_test
And and if you run the programm it will output this:
1, 2, 3, 4
But it's better to use references like this (i would say):
void getValues(int& a, unsigned& b, string& c, int& d)
{
a = 1;
b = 2;
c = "3";
d = 4;
}
int main()
{
...
getValues(a, b, c, d)
...
}
Uch thats what I get for not reading the question carefully...
Can a function only return one value, unless it is a pointer to an array?
Yeah you only can return 1 single value, but this single value can include multiply values (struct, class, array).
You can return multiple data items using a structure but using pointer (I don't understand this) will use memory more efficiently. Is this correct?
True. But when you use pointers it depends on how you use it.
When you dynamic allocate it each function call it wont be very efficient and you would need to deallocate the memory manually after usage. When you use a global-array/struct it will be efficient. But can give you problems when you call the function multiply times.
In addition to what is already said in this thread, in C++11 you can return structures initialized using uniform initialization:
struct XYZ {
int x;
int y;
int z;
};
XYZ foo() {
return {1, 2, 3};
}
Personally I prefer returning structures with named members rather than tuples because the latter doesn't provide names for its members.
That is correct.
You can however "return" multiple items, by adding parameters that are passed by reference, then writing the multiple results to them.
A function can indeed only return one 'thing' with its return statement. That thing can, however, be a pointer (C & C++ arrays are simply pointers in disguise), a reference (a pointer which can't be reseated or array-indexed) or an object, which may encapsulate multiple things.
If you return a structure, you're passing back the entire structure. If you return a pointer or reference, you are returning only the address of the structure - so you had better not return a reference or pointer to a structure that goes out of scope when the function returns! Doing so invokes undefined behavior, which most likely (but not always) is a segmentation fault.
If you want a bigger picture about this read about passing parameters by value and passing by reference it also applies for returning parameters.
As you mentioned:
You can return multiple data items using a structure but using pointer (I don't understand this) will use memory more efficiently. Is this correct?
Lets say you have some structure:
struct BigStructure{
int array[1000];
double otherData[1000];
//... etc
};
and some method:
BigStructure workWhenCopying(BigStructure bigStruct){
// some work with a structure
return bigStruct;
}
This method illustrates the case when you pass parameters to the method and return it by value, which means that each time you call this method you are copying the method's argument into another place in memory. This copying takes time and when you have bigger structures it slows down your program run time thus it is more efficient to pass big structures by reference.
void workWithReference(BigStructure & bigStruct){
// do some work
}
In this case you are not copying whole data structure, just passing the address of the memory where this structure resides. You also don't need a return statement since changes to that structure object will be visible outside this method. But if you will reassign bigStruct to a new memory location it will be visible only within local method: workWithReference
I hope it's more clearer now;)
Suppose there is a structure such as:
struct XYZ
{
double a;
double b;
}
Now we make an object of it
struct XYZ abcd[10];
and now I am filling this array.
I have to initialize this array because I call this in a loop and it overwrites the previous values.
If it overwrites the previous 5 values by 4 new values then still the 5th one is still there in the array which results in the wrong output.
If you use c++ you can define a constructor, observe:
struct XYX {
double a, b;
XYX() { a=0; b=0; }
}
Initializing a struct is easily done by enumerating it's member values inside curly braces. Beware, though, 'cause if a member is omitted from the enumeration, it will be regarded as zero.
struct A { int a_, b_; };
A a = { 1, 2 };
A b = { 1 }; // will result in a_=1 and b_=0
A as [] = { {1,2}, {1,3}, {2,5} };
Strangely enough, this also works for the public members of an "aggregate" class. It's to be discouraged, though, since this way your class will lose it's ability to do the necessary things at construction time, effectively reducing it to a struct.
for (int i=0; i<10; ++i)
{
abcd[i].a = 0.0;
abcd[i].b = 0.0;
}
Of course, if some of the slots haven't been filled with meaningful data you probably shouldn't be looking at them in the first place.
If your question is how to initialize the array elements then #cemkalyoncu answer will help you.
If it over rites the previous 5 values
by 4 new values then still the 5th one
is still there in the array which in
result gives wrong output.
For this case it is better you go for vector.
You can remove the unwanted elements from the vector to make sure that it does not contain the wrong values.
In this case, remove 5th element from vector if you no longer use.
In addition to xtofl's answer, note, that if you want to zero-initialize the array, all you have to do is write
XYZ abcd[10] = {};
Also you can initialize with memset function
memset(&abcd[index], 0, sizeof(XYZ));