Need a little help changing my array to a vector.

Started by
8 comments, last by DevFred 14 years, 7 months ago
D3D9 VC++ I'll try to present this as a spot-the-mistake. I haven't used vectors for a long time so I'm not sure what I'm missing. What worked:

#include "VertexDefs.h"

static const TEXTDVERTEX	verts[] = {	
    {-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f},
    {511.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f},
    {-0.5f, 511.5f, 0.0f, 1.0f, 0.0f, 1.0f},

    {-0.5f, 511.5f, 0.0f, 1.0f, 0.0f, 1.0f},
    {511.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f},
    {511.5f, 511.5f, 0.0f, 1.0f, 1.0f, 1.0f} };

									
    void*  pVerts;
		
    if(FAILED(m_pVertexBuffer->Lock(0, sizeof(verts), (void**)&pVerts, NULL)))
    {
	return E_FAIL;
    }

    memcpy(pVerts, &verts, sizeof(verts));
    m_pVertexBuffer->Unlock();


///////////////// My TEXTDVERTEX struct /////////////////////////

struct TEXTDVERTEX
{
    float	x,y,z,rhw,u,v;
};

This simply renders a quad with a texture that is opened later. I want to stop using the array and start using a vector. Here's what doesn't work:

#include "VertexDefs.h"
#include <vector>

/////////////// Later, in the same {} scope ... //////////////////////
{
    vector <TEXTDVERTEX>	verts;

TEXTDVERTEX* temp1 = new TEXTDVERTEX(-0.5f,	-0.5f,  0.0f, 1.0f, 0.0f, 0.0f);
verts.push_back(*temp1);
delete temp1;

TEXTDVERTEX* temp2 = new TEXTDVERTEX(511.5f, -0.5f,  0.0f, 1.0f, 1.0f, 0.0f);
verts.push_back(*temp2);
delete temp2;

TEXTDVERTEX* temp3 = new TEXTDVERTEX(-0.5f,  511.5f, 0.0f, 1.0f, 0.0f, 1.0f);
verts.push_back(*temp3);
delete temp3;

TEXTDVERTEX* temp4 = new TEXTDVERTEX(511.5f, -0.5f,  0.0f, 1.0f, 1.0f, 0.0f);
verts.push_back(*temp4);
delete temp4;

TEXTDVERTEX* temp5 = new TEXTDVERTEX(511.5f, 511.5f, 0.0f, 1.0f, 1.0f, 1.0f);
verts.push_back(*temp5);
delete temp5;

TEXTDVERTEX* temp6 = new TEXTDVERTEX(-0.5f,  511.5f, 0.0f, 1.0f, 0.0f, 1.0f);
verts.push_back(*temp6);
delete temp6;



    void* pVerts;
    if(FAILED(m_pVertexBuffer->Lock(0, sizeof(verts), (void**)&pVerts, NULL)))
    {
	return E_FAIL;
    }

    memcpy(pVerts, &verts, sizeof(verts));					
    m_pVertexBuffer->Unlock();	
}

//////////// I added a quick ctor to the TEXTDVERTEX struct /////////////////

struct TEXTDVERTEX
{
TEXTDVERTEX(float xx, float yy, float zz, float rrhw, float uu, float vv):
		x(xx), y(yy), z(zz), rhw(rrhw), u(uu), v(vv){}

	float	x,y,z,rhw,u,v;
};

Compiles fine, nothing appears. Anything obvious I've missed? Thanks if anyone spots it.
Advertisement
A few things:

{    vector <TEXTDVERTEX>	verts;// There's no need to dynamically allocate the verticesverts.push_back(TEXTDVERTEX(-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f));verts.push_back(TEXTDVERTEX(511.5f, -0.5f,  0.0f, 1.0f, 1.0f, 0.0f));// Etc.    TEXTDVERTEX* pVerts;    // sizeof(verts) gives the size of the std::vector object, not the size of the data it holds    // Also, if this should lock the entire buffer, just pass 0    if(FAILED(m_pVertexBuffer->Lock(0, sizeof(TEXTDVERTEX) * verts.size(), (void**)&pVerts, NULL)))    {	return E_FAIL;    }    // You should probably use std::copy() for this    // Something like:    // std::copy(verts.begin(), verts.end(), pVerts);    // I'm not sure if the above call works as written (I'm not great with STL algorithms)    memcpy(pVerts, &verts[0], sizeof(TEXTDVERTEX) * verts.size());					    m_pVertexBuffer->Unlock();	}
Many thanks, I'll try this out.

Edit - Excellent.

One critical thing I needed to learn is that it appears that for a vector, &verts != &verts[0]. That was the last mistake that got it working. Also, the sizeof() business as well.

Changing the void pointers to TEXTDVERTEX pointers makes no difference, but I will it anyway if for nothing but clarity.


Thanks again. I was worried I was asking a bit much but really, I would have spent hours trying to find those little things I once knew. I have been assuming that you could treat a vector almost exactly like an array, so I would have been looking in the wrong places probably until tomorrow or worse.

Instead I went to the shops and you saved me a tonne of time.

[Edited by - Defend on September 19, 2009 1:59:08 PM]
Quote:Original post by Defend
it appears that for a vector, &verts != &verts[0].

It is also not the same for arrays as the following program demonstrates.

#include <iostream>#include <typeinfo>int main(){    int array[10];    std::cout << typeid( array   ).name() << '\n';    std::cout << typeid(&array   ).name() << '\n';    std::cout << typeid(&array[0]).name() << '\n';    std::cout << "--------\n";    std::cout << &array[0]     << '\n';    std::cout << &array[0] + 1 << '\n';    std::cout << "--------\n";    std::cout << &array        << '\n';    std::cout << &array    + 1 << '\n';    std::cout << "--------\n";    std::cout << sizeof( array   ) << '\n';    std::cout << sizeof(&array[0]) << '\n';}/*A10_iPA10_iPi--------0x22ff340x22ff38   <--- + 4--------0x22ff340x22ff5c   <--- +40--------404*/

Basically, &array gives you a pointer to the entire array, whereas &array[0] gives you a pointer to the first element. The address is the same, but the type differs. You notice that when you do pointer arithmetic. Note that &array[0] is not the same as array -- the types differ, and sizeof gives different results.
Quote:Original post by Defend
I want to stop using the array and start using a vector. Here's what doesn't work:

Why? In this case I'd say stick with the array. The static const array is simply placed in the read-only section of the executable. The alternative is dynamic memory allocation with the vector. And actually, you do it in a rather stupid manner. If you *really* want a vector, consider the following instead:

vector <TEXTDVERTEX> verts;verts.push_back(TEXTDVERTEX(-0.5f,   -0.5f, 0.0f, 1.0f, 0.0f, 0.0f));verts.push_back(TEXTDVERTEX(511.5f,  -0.5f, 0.0f, 1.0f, 1.0f, 0.0f));verts.push_back(TEXTDVERTEX(-0.5f,  511.5f, 0.0f, 1.0f, 0.0f, 1.0f));verts.push_back(TEXTDVERTEX(511.5f,  -0.5f, 0.0f, 1.0f, 1.0f, 0.0f));verts.push_back(TEXTDVERTEX(511.5f, 511.5f, 0.0f, 1.0f, 1.0f, 1.0f));verts.push_back(TEXTDVERTEX(-0.5f,  511.5f, 0.0f, 1.0f, 0.0f, 1.0f));


But for anything which is a fixed size, just use an array, IMO.
Million-to-one chances occur nine times out of ten!
Quote:Original post by Mike nl
Quote:Original post by Defend
I want to stop using the array and start using a vector. Here's what doesn't work:

Why? In this case I'd say stick with the array. The static const array is simply placed in the read-only section of the executable. The alternative is dynamic memory allocation with the vector. And actually, you do it in a rather stupid manner. If you *really* want a vector, consider the following instead:

*** Source Snippet Removed ***

But for anything which is a fixed size, just use an array, IMO.



Or if you know it's a fixed size vector you're better off using std::array's instead.
Mike nl, this is test code. Two triangles on the screen are not my final goal - the vector size will indeed be dynamic. Thanks for the criticism without addressing the question though. At least you repeated someone else's reply, I guess that's worth something.

DevFred.. o.O. Gah, I didn't know that either. I swear my uni professor taught us otherwise... many years ago and possibly in Java. Thanks for catching that and taking the time to post the proof.
Quote:Original post by Defend
DevFred.. o.O. Gah, I didn't know that either. I swear my uni professor taught us otherwise...

In most contexts, an array name is converted to a pointer to its first element silently. That's why many people assume that arrays and pointers are the same. They are not!
int array[10];int *p =  array;        // silent array-to-pointer decayint *q = &array[0];     // this might look more natural...int *q = &(*(array+0)); // ...but it's just decay in disguise!                        // * and & cancel each other out, and +0 is a no-op

The last two lines need explaining. The "array" indexing operator [] is not defined for arrays (read that again!), only for pointers. a is always converted to *(a + i), no matter if a is an array or a pointer. Addition is not defined for arrays, so in this context, the array is silently converted to a pointer to its first element.

Array-to-pointer decay does not cost anything, because the compiler knows the address of the array and its element type anyway. It also doesn't involve any additional variables. Note that the generated pointer is an rvalue. That is, you cannot say array = NULL or something similar.
Yeah I'm sure that prof was actually making a big deal about how they are the same thing. But yes I see; same address, different types. An array type is not a pointer type is not a first-element-of-the-array type. And I see... r-value.

Therefore, declaring a pointer and using [] to work with it like an array is actually a little less secure than declaring an array, right?
Quote:Original post by Defend
Therefore, declaring a pointer and using [] to work with it like an array is actually a little less secure than declaring an array, right?

Yes. If you declare an array, you have the storage where you put the elements. If you declare a pointer, you must think about where that pointer should point to and initialize it accordingly before you can use it.

(The program you posted was somehow special in this regard, because here you call a function that makes the pointer point to the actual data.)

This topic is closed to new replies.

Advertisement