Touble with passing a reference to vector of vectors of objects

H

hardwareman

Hi Folks,

I can work around this problem, but it shows a problem in my
understanding of how things should work. Any ideas are appreciated.

Thanks,
Hardwareman

When the following subroutine is put inline the results are expected.
When the reference to the vector is passed, the reference has the
correct sizes but the 'Print' member function spews almost random junk.

BLAH is an unordinary user class containing scalars.

typedef vector<BLAH> EntryBram_T ;
typedef vector<EntryBram_T> Expected_T ;

void C_PrintExpected ( Expected_T & expected ) {
for (int i=0 ; i < expected.size() ; i++) {
Msg(MSG_LOW, "%m: C_PrintExpected: terminal=%d list size=%d\n",
i, expected.size() ) ;
int j = 0 ;
// print out all expected entries
while (j < expected.size() ) {
(expected)[j].Print(j++) ;
}
}
}


The calling function:

expected[ term ].push_back( EntryBram[original_start] ) ;
Msg(MSG_LOW, "%m: Print what we just pushed\n") ;
(expected[ term ].end()-1)->Print(original_start) ; // this is
fine
C_PrintExpected(expected) ; // THIS IS
WRONG

// This inline code works as expected
for (int i=0 ; i < expected.size() ; i++) {
Msg(MSG_LOW, "%m: C_PrintExpected inline: terminal=%d list
size=%d\n",
i, expected.size() ) ;
int j = 0 ;
// print out all expected entries
while (j < expected.size() ) {
(expected)[j].Print(0) ;
j++ ;
}
}

////////////////
RUN RESULTS:

BAD :
C_PrintExpected: terminal=0 list size=1
BLAH::print add=0x0000: mac=00:00:01 hdlc_len=0x000

GOOD :
C_PrintExpected inline: terminal=0 list size=1
BLAH::print add=0x0000: mac=23:24:25 hdlc_len=0x031
 
G

Geo

hardwareman said:
Hi Folks,

I can work around this problem, but it shows a problem in my
understanding of how things should work. Any ideas are appreciated.

Thanks,
Hardwareman

When the following subroutine is put inline the results are expected.
When the reference to the vector is passed, the reference has the
correct sizes but the 'Print' member function spews almost random junk.

BLAH is an unordinary user class containing scalars.

typedef vector<BLAH> EntryBram_T ;
typedef vector<EntryBram_T> Expected_T ;

void C_PrintExpected ( Expected_T & expected ) {
for (int i=0 ; i < expected.size() ; i++) {
Msg(MSG_LOW, "%m: C_PrintExpected: terminal=%d list size=%d\n",
i, expected.size() ) ;
int j = 0 ;
// print out all expected entries
while (j < expected.size() ) {
(expected)[j].Print(j++) ;
}
}
}


The calling function:

expected[ term ].push_back( EntryBram[original_start] ) ;
Msg(MSG_LOW, "%m: Print what we just pushed\n") ;
(expected[ term ].end()-1)->Print(original_start) ; // this is
fine
C_PrintExpected(expected) ; // THIS IS
WRONG

// This inline code works as expected
for (int i=0 ; i < expected.size() ; i++) {
Msg(MSG_LOW, "%m: C_PrintExpected inline: terminal=%d list
size=%d\n",
i, expected.size() ) ;
int j = 0 ;
// print out all expected entries
while (j < expected.size() ) {
(expected)[j].Print(0) ;
j++ ;
}
}

////////////////
RUN RESULTS:

BAD :
C_PrintExpected: terminal=0 list size=1
BLAH::print add=0x0000: mac=00:00:01 hdlc_len=0x000

GOOD :
C_PrintExpected inline: terminal=0 list size=1
BLAH::print add=0x0000: mac=23:24:25 hdlc_len=0x031


First off, the code in the function is not the same as the inlined
code, however I'm not sure if the '.' in the line

(expected)[j].Print(j++) ;

counts as a sequence point, if not then you have UB, and therefore you
should nothave any expectations of what should happen.
 
Z

Zara

-- non-inline--
while (j < expected.size() ) {
(expected)[j].Print(j++) ;

doesn't work: because the argument to the function is evaluated before
the object reference, so the first time it works like:
(expected)[1].Print(0)
;

-- inline --
while (j < expected.size() ) {
(expected)[j].Print(0) ;
j++ ;
}

works ONLY the first time in the loop. Maybe it sould have been:
while (j < expected.size() ) {
(expected)[j].Print(j) ;
j++ ;
}
 
H

hardwareman

Thanks for the sequence point note. You are right on. Seperating
into:
(expected)[j].Print(j) ;
j++ ;

corrects the problem.
Thanks!
 
P

Peter Julian

hardwareman said:
Hi Folks,

I can work around this problem, but it shows a problem in my
understanding of how things should work. Any ideas are appreciated.
<snip>

nasty code. Why don't you reproduce compileable code with a
std::vector< std::vector<int> > container?

If you can't make it work with an int, it won't work with a Blaah.

To use an iterator, you need to typedefine it (since containers, like
vector, have their own predefined set of iterator types and in many cases,
STL containers define their own specialized iterators).

There are other ways of doing this, namely with algorithms. But that doesn't
mean you can ignore iterators (thats what the algorithms use for the most
part).

#include <iostream>
#include <vector>

void Print( std::vector< std::vector<int> >& r_vv)
{
typedef std::vector< std::vector<int> >::iterator VVIter;
VVIter it = r_vv.begin();

for (it; it != r_vv.end(); ++it)
{
typedef std::vector<int>::iterator VIter;
VIter niter = (*it).begin();
for (niter; niter != (*it).end(); ++niter)
{
std::cout << *niter << " ";
}
std::cout << std::endl;
}
}

int main()
{
std::vector< std::vector<int> > v_vn;

for (int i = 0; i < 10; ++i)
{
std::vector<int> vn(10, i); // create container with 10 elements
// having the value of i

v_vn.push_back(vn); // push container into master container
}

Print(v_vn);

return 0;
}

/*
0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2 2
3 3 3 3 3 3 3 3 3 3
4 4 4 4 4 4 4 4 4 4
5 5 5 5 5 5 5 5 5 5
6 6 6 6 6 6 6 6 6 6
7 7 7 7 7 7 7 7 7 7
8 8 8 8 8 8 8 8 8 8
9 9 9 9 9 9 9 9 9 9
*/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,767
Messages
2,569,571
Members
45,045
Latest member
DRCM

Latest Threads

Top