How can I access variables in vector<struct> *obj? - vector

How would I get my variables out of a vector?
I can't use the binary insertion operators or the equal operators.
Earlier, I declared a vector<someStruct> *vObj and allocated it, then returned the vObj
and called it in this function:
vector<sameStruct> firstFunc();
for (unsigned int x = 0; x < v->size(); x++)
{
v[x];
}
when I debug it, v[x] now has the full contents of the original vector, as it did before without the subscript/index.
But I don't think I've done anything to progress beyond that.
I just have about 4 variables inside my vector; when I debug it, it has the information that I need, but I can't get to it.

As it is written v is a pointer to a vector of structs.
When you index directly into v all you are doing is pointer arithmatic. v[x] is the vector of structs at position x (assuming that v is an array if it is just a single object at the end of the pointer then v[x] for x>0 is just garbage). This is because it is applying the [x] not to the vector pointed to by v but to the pointer v itself.
You need to dereference the pointer and then index into the vector using something like:
(*v)[x];
At this point you have a reference to the object at the xth position of the vector to get at its member functions / variables use:
(*v)[x].variable;
or
(*v)[x].memberfunction(parameters);
If you do not want to dereference the vector then access the element within it you might try something like:
v->at(x);
v->at(x).variable;
v->at(x).memberfunction;
This way you are accessing a member function of an object in exactly the same manner as when you called:
v->size();
I hope that this helps.

To use the [] operator to access elements you must do so on object, not a pointer to an object.
Try;
(*vec)[x];
E.g.
for (int i = 0; i < vec->size(); i++)
{
printf("Value at %d is %d\n", i, (*vec)[i]);
}
Note that when calling functions on a pointer you usually use the -> operator instead of the . operator, but you could easily do (*vec).some_func(); instead.
Operators such as [], --, ++ and so on can act both on objects and pointers. With objects they act as function calls, but on pointers they act as mathematical operations on the address.
For example;
pointer[nth];
*(pointer + nth);
Have exactly the same effect - they return the nth object from the start of the pointer. (note the location of the * in the second example, it's called after the offset is applied.
Two other tips;
You can also avoid the need to dereference like this by passing the vector as a reference, not a pointer. It's not always a suitable option but it does lead to cleaner code.
void my_func(std::vector<int>& vector)
{
// vector can then be used as a regular variable
}
If you're going to be passing vectors of a specific type to functions a lot then you can use a typedef both for clarity and to save on typing.
typedef std::vector<int> IntVector;
void my_func(IntVector& vector)
{
}

Related

Method does not change the value of object if the object is in a slice

Here is my program:
package main
import (
"fmt"
)
type Number struct {
val int
}
func (num * Number) Increment () {
num.val += 1
}
func (num Number) Value() int {
return num.val
}
func main() {
numbers := []Number {
{val: 12},
{val: 7},
{val: 0},
}
for _, each := range numbers {
each.Increment()
fmt.Println(each.Value())
}
for _, each := range numbers {
fmt.Println(each.Value())
}
}
Here is the output:
13
8
1
12
7
0
First question: why does the Increment()method not update the value in the first for loop? I used pointer as the receiver so that val can be updated for sure, but why would the second for loop print out the original values of those Numbers?
Second question: what can be done so that when I iterate over a slice of Numbers and invoke the Increment() method, all Numbers are correctly incremented?
[Edit] I noticed that if I use index-based for loop and invoke the Increment() method, values will be correctly updated. Why?
for i := 0; i < len(numbers); i++ {
numbers[i].Increment()
}
This for range loop:
for _, each := range numbers {
iterates over the elements of the numbers slice, and in each iteration it assigns (copies) an element to the each loop variable.
Since your numbers slices is of type []Number, it will copy the Number struct into the each variable (whose type will be Number).
Then you call the Number.Increment() method on this variable. Since Increment() has pointer receiver, this is a shorthand for (&each).Increment(). So the address of this loop variable is taken and used as the receiver for the Increment() method. The Increment() method will properly change this loop variable, but this is independent, distinct, detached from the slice, so you are not modifying the element in the slice.
When you do:
for i := 0; i < len(numbers); i++ {
numbers[i].Increment()
}
Elements of numbers are not copied here. This:
numbers[i].Increment()
Indexes the numbers slice, and since Increment() has a pointer receiver, the address of numbers[i] is taken and used, which is the address of the element in the slice. So here, you will modify the Number struct value of the slice.
Note that you can also use for range here:
for i := range numbers {
numbers[i].Increment()
}
The first iteration variable when ranging over a slice is the index.
Also, if you would store pointers in your numbers slice (which would then have type of []*Number), the same thing would happen, but in that case the for range would copy pointers, not structs, and the pointer in the loop variable would point to the same Number struct value as the pointer in the slice would, so that would also work with your first for range variant.
All these are detailed in Spec: For statements, in the For statements with range clause subsection.
In your original version, the loop variable each is a copy of the Number struct. Notice that it is not a pointer to it, nor is it the copy of a pointer to it. That means, that there is a newly created Number in each iteration. You call a method on a pointer to this newly created instance, then it gets destroyed after the loop and your original data has not changed.
If you would instead use numbers := []*Number { ... and iterate over that, the each variable would be the copy of a pointer to Number. Using copies of pointers is the same as using pointers, because the copy points to the same memory location, thus if you then call the method, the data in the slice wil change.
For your edit: if you use numbers[i] then you reference the data inside the slice, obviously. As I stated above, the for range loop will create a copy of the items in its each variable.
Whenever you loop through the slice it creates a copy of original variable which is used as value and is incremented. But when you are using the index you are pointing to the value backed at that address which is than incremented and hence original value got changed.
Print the value of both variable to see the changes as:
for i, each := range numbers {
each.Increment()
fmt.Println(each, numbers[i])
}
you can also print the address of variable in a loop with the original value address to see that both variables have different address. Hence you are actually creating a local variable when iterating over numbers.
for i, each := range numbers {
each.Increment()
fmt.Printf("%p -- %p\n",&each, &numbers[i])
}
Working Code to check address on Go Playground

Will an array of pointers be equal to an array of chars?

I have got this code:
import std.stdio;
import std.string;
void main()
{
char [] str = "aaa".dup;
char [] *str_ptr;
writeln(str_ptr);
str_ptr = &str;
*(str_ptr[0].ptr) = 'f';
writeln(*str_ptr);
writeln(str_ptr[0][1]);
}
I thought that I am creating an array of pointers char [] *str_ptr so every single pointer will point to a single char. But it looks like str_ptr points to the start of the string str. I have to make a decision because if I am trying to give access to (for example) writeln(str_ptr[1]); I am getting a lot of information on console output. That means that I am linking to an element outside the boundary.
Could anybody explain if it's an array of pointers and if yes, how an array of pointers works in this case?
What you're trying to achieve is far more easily done: just index the char array itself. No need to go through explicit pointers.
import std.stdio;
import std.string;
void main()
{
char [] str = "aaa".dup;
str[0] = 'f';
writeln(str[0]); // str[x] points to individual char
writeln(str); // faa
}
An array in D already is a pointer on the inside - it consists of a pointer to its elements, and indexing it gets you to those individual elements. str[1] leads to the second char (remember, it starts at zero), exactly the same as *(str.ptr + 1). Indeed, the compiler generates that very code (though plus range bounds checking in D by default, so it aborts instead of giving you gibberish). The only note is that the array must access sequential elements in memory. This is T[] in D.
An array of pointers might be used if they all the pointers go to various places, that are not necessarily in sequence. Maybe you want the first pointer to go to the last element, and the second pointer to to the first element. Or perhaps they are all allocated elements, like pointers to objects. The correct syntax for this in D is T*[] - read from right to left, "an array of pointers to T".
A pointer to an array is pretty rare in D, it is T[]*, but you might use it when you need to update the length of some other array held by another function. For example
int[] arr;
int[]* ptr = &arr;
(*ptr) ~= 1;
assert(arr.length == 1);
If ptr wasn't a pointer, the arr length would not be updated:
int[] arr;
int[] ptr = arr;
ptr ~= 1;
assert(arr.length == 1); // NOPE! fails, arr is still empty
But pointers to arrays are about modifying the length of the array, or maybe pointing it to something entirely new and updating the original. It isn't necessary to share individual elements inside it.

Adding one to a vector

I am trying to translate c code into MATLAB, and I have come across some code that I don't understand. Specifically, there is a variable defined as:
static float *lpfdata;
This gets assigned during a function call to:
envelope_old(&fdata[0], lpfdata, winlength, samprate, BW);
Which accepts input as:
void envelope_old (float *fdata, float *lpfdata, int nsamps, int samprate,
float cutoff)
Within envelope_old, lpfdata is referenced as a vector, being assigned values in a loop in the format "lpfdata[i] = ..." where i is the index variable in the loop.
Later, a function call in the format:
downsample( lpfdata+1, dwndata, winlength, downby);
is called. What does the +1 mean in this instance?
When dealing with a pointer, lpfdata[n] and lpfdata+n are the same - they both add n * sizeof(*lpfdata) to the raw pointer and access the memory at that address.
In this case, lpfdata points to elements of type float, so sizeof(*lpfdata) == sizeof(float)

QMap Memory Error

I am doing one project in which I define a data types like below
typedef QVector<double> QFilterDataMap1D;
typedef QMap<double, QFilterDataMap1D> QFilterDataMap2D;
Then there is one class with the name of mono_data in which i have define this variable
QFilterMap2D valid_filters;
mono_data Scan_data // Class
Now i am reading one variable from a .mat file and trying to save it in to above "valid_filters" QMap.
Qt Code: Switch view
for(int i=0;i<1;i++)
{
for(int j=0;j<1;j++)
{
Scan_Data.valid_filters[i][j]=valid_filters[i][j];
printf("\nValid_filters=%f",Scan_Data.valid_filters[i][j]);
}
}
The transferring is done successfully but then it gives run-time error
Windows has triggered a breakpoint in SpectralDataCollector.exe.
This may be due to a corruption of the heap, and indicates a bug in
SpectralDataCollector.exe or any of the DLLs it has loaded.
The output window may have more diagnostic information
Can anyone help in solving this problem. It will be of great help to me.
Thanks
Different issues here:
1. Using double as key type for a QMap
Using a QMap<double, Foo> is a very bad idea. the reason is that this is a container that let you access a Foo given a double. For instance:
map[0.45] = foo1;
map[15.74] = foo2;
This is problematic, because then, to retrieve the data contained in map[key], you have to test if key is either equal, smaller or greater than other keys in the maps. In your case, the key is a double, and testing if two doubles are equals is not a "safe" operation.
2. Using an int as key while you defined it was double
Here:
Scan_Data.valid_filters[i][j]=valid_filters[i][j];
i is an integer, and you said it should be a double.
3. Your loop only test for (i,j) = (0,0)
Are you aware that
for(int i=0;i<1;i++)
{
for(int j=0;j<1;j++)
{
Scan_Data.valid_filters[i][j]=valid_filters[i][j];
printf("\nValid_filters=%f",Scan_Data.valid_filters[i][j]);
}
}
is equivalent to:
Scan_Data.valid_filters[0][0]=valid_filters[0][0];
printf("\nValid_filters=%f",Scan_Data.valid_filters[0][0]);
?
4. Accessing a vector with operator[] is not safe
When you do:
Scan_Data.valid_filters[i][j]
You in fact do:
QFilterDataMap1D & v = Scan_Data.valid_filters[i]; // call QMap::operator[](double)
double d = v[j]; // call QVector::operator[](int)
The first one is safe, and create the entry if it doesn't exist. The second one is not safe, the jth element in you vector must already exist otherwise it would crash.
Solution
It seems you in fact want a 2D array of double (i.e., a matrix). To do this, use:
typedef QVector<double> QFilterDataMap1D;
typedef QVector<QFilterDataMap1D> QFilterDataMap2D;
Then, when you want to transfer one in another, simply use:
Scan_Data.valid_filters = valid_filters;
Or if you want to do it yourself:
Scan_Data.valid_filters.clear();
for(int i=0;i<n;i++)
{
Scan_Data.valid_filters << QFilterDataMap1D();
for(int j=0;j<m;j++)
{
Scan_Data.valid_filters[i] << valid_filters[i][j];
printf("\nValid_filters=%f",Scan_Data.valid_filters[i][j]);
}
}
If you want a 3D matrix, you would use:
typedef QVector<QFilterDataMap2D> QFilterDataMap3D;

Problems with a structure copy

I am having a compiler issue in Visual Studio 2005 using the standard C compiler when trying to do a structure copy from one location to another.
The types are defined in a file as follows:
definition.h
#define MAX 7
typedef struct{
char recordtext[18];
boolean recordvalid;
}recordtype;
typdef recordtype tabletype[MAX];
typedef struct{
tabletype table;
}global_s;
Let us pretend that a global_s "object" is instantiated and initialized somewhere and a pointer to this structure is created.
#include "definition.h"
global_s global;
global_s* pglobal = &global;
init(&pglobal);
Meanwhile, in another file (and this is where my problem is) i am trying to create a local tabletype object, and fill it with the global table member, using a get method to protect the global (lets pretend it is "static")
#include "definition.h"
extern global_s* pglobal;
tabletype t;
gettable(&t);
void gettabl (tabletype* pt)
{
*pt = pglobal->table;
}
When I go to compile, the line in the gettable function throws a compiler error "error C2106: '=': left operand must be l-value. It looks as though this should behave as a normal copy operation, and in fact if I perform a similar operation on a more basic structure I do not get the error. For example If I copy a structure only containing two integers.
Does anyone have a solid explanation as to why this operation seems to be incorrect?
(Disclaimer: I have developed this code as a scrubbed version of my actual code for example purposes so it may not be 100% correct syntactically, I will edit the question if anyone points out an issue or something needs to be clarified.)
It's the arrays in the struct; they cannot be assigned. You should define an operator=() for each of the structs, and use memcpy on the arrays, or copy them in a loop element by element.
(IF you want to get a reference to your global variable):
I am not sure, if this is correct (and the problem), but I think besides function prototypes, arrays and pointers (to arrays 1. element) are NOT exactly the same thing. And there is a difference between pointer to array and pointer to the 1. element of an array)
Maybe taking the adress of the array:
*pt = &(pglobal->table);
Anyway it might be better not to fetch the address of the whole array but the address of the first element, so that the resulting pointer can be used directly as record array (without dereferencing it)
recordtype* gettable (size_t* puLength)
{
*puLength = MAX;
return &(pglobal->table[0]);
}
(IF you want a copy of the table):
Arrays can't be copied inplace in C90, and of course you have to provide target memory. You would then define a function get table like this:
void gettable (recordtype * const targetArr)
{
size_t i = 0;
for (; i < MAX; i++) targetArr[i] = pglobal->table[i];
return;
}
an fully equivalent function prototype for gettable is:
void gettable(recordtype[] targetArr);
Arrays are provided by refernce as pointer to the first element, when it comes to function parameters. You could again ask for an pointer to the whole array, and dereference it inside gettable. But you always have to copy elementwise.
You can use memcopy to do the job as 1-liner. Modern compilers should generate equally efficent code AFAIK.

Resources