Is there any advantage to this?

Say I have this...
1
2
3
4
5
6
struct st1
{
    vector<long> vec;  // Has millions of elements
};

vector<st1*> vec_pst1;


I want to access st1::vec many times. Would there by an advantage to doing it one of the following ways?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
vector<long> st1::*pvec = &st1::vec;
long l;

for (int i = 0 ; i < 2000; ++i) {
    st1 * p = vec_pst1[i];
    for (int j = 0; j < 25000000; ++j) {
         l = p->*pvec[j]; 
    }
} 

// or this way
for (int i = 0 ; i < 2000; ++i) {
    for (int j = 0; j < 25000000; ++j) {
         l = vec_pst1[i]->vec[j]; 
    }
} 


Is there a way to get a pointer to a vec of a specific instance of st1? I'd rather not have to reference st1 to get to its vec. I just want to go straight there. I have a feeling these two ways are essentially equivalent in terms of efficiency.
I think I'd replace that first version with

1
2
3
4
5
6
7
8
9
10
	typedef vector<long> l_vec ;

	long l;

	for (int i = 0 ; i < 2000; ++i) {
		const l_vec & v = vec_pst1[i]->vec ;
		for (int j = 0; j < 25000000; ++j) {
			l = v[j] ;
		}
	}


A pointer to member isn't really want you want. And yes, they should be equivalent for purposes of efficiency.

Without optimisations the first version may be slower because when you access a member with a pointer to member the member offset is potentially unknown.
cire, does your way give a performance enhancement over mine? It seems like it since you don't have to dereference the pointer to st1 to access something in v - you only have to dereference once when getting the address of vec.


aquaz, isn't the member offset known because of this line?

 
vector<long> st1::*pvec = &st1::vec;


It seems to me like it should since all st1 instances will have vec offset to the same position. No?
No, the principle of members to pointers is to access members at offset unknown at compile time.
Of course in your example if you compile with optimisations a decent compiler can guess it since pvec is invariant.
Take this example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class A
{
public:
	int a; 
};

int main()
{
	A a = {5};
	A* pa = &a;
	int A::*p = &A::a;
	int i;
	i = pa->*p;
	i = pa->a;
	return 0;
}

If you compile this in Debug in Visual 2010 and disassemble, you can see that line i = pa->*p generate 1 extra "add" instruction to add the value of p to the register which hold the adress of pa. Line i = pa->a doesn't need this instruction because the compiler know the offset of a. In fact members to pointers are just integers which hold the offset of the member variable into the class but i don't think you need it for your problem.

And don't think too much about the performances between two similar pieces of code, the compiler can do optimisations you can't even imagine. For the example of cire, it will have a performance gain without optimisation but with optimisations decent compilers are able to see the expression vec_pst1[i]->vec is invariant within the second for so it will transform your code like the one proposed by cire to avoid recomputing it each time.
Topic archived. No new replies allowed.