std::vector create reference to element or use .at()/[]?

I have a std::vector that stores textures. I need to contantly render them to the screen. Would it be faster to create a reference or pointer to the texture and render using the reference or should I just get the texture directly from the vector each time?
Last edited on
Both vector::at and vector operator[] give you a reference. So long as you can guarantee that nothing will happen to the actual texture in the vector while you're rendering it (e.g. in another thread) then creating a copy seems a waste of time; just use that reference.
Last edited on
No, saving a reference to it and then [de]referencing that reference instead of using at()/operator[] is no more or less efficient. And by separating the reference from the container itself (presumably beyond a single function's scope), you're making it less maintainable because now you have to worry about if the container re-allocated after being resized somewhere else in the code. You're trying to micro-optimize for no good purpose, as far as I can tell (though this is a guess, because obviously I'm not looking at the actual code). (If we were dealing with a linked list instead of a vector, this might be a different story.)

If there's a speed issue currently happening, it's most likely something else.
If you're doing Texture texture = texture_pool[texture_index];, then you're making a copy of the texture, which might be inefficient if copying a texture means copying its pixel information.
You would do something like
Texture& texture = texture_pool[texture_index]; instead. (Or just use the texture_pool[texture_index] directly with whatever operation.)
Last edited on
Using std::vector<>::at() is expensive; it performs bounds checking, it may throw, so an exception frame would be built.

Validate the position once, and then use the inexpensive std::vector<>::operator[]() from then on.
True, I forgot to mention that difference. (Artem was grouping them together to differentiate from making a separate reference variable, I think.)
then creating a copy seems a waste of time


I didn't mean creating a copy. I was asking if I should render them like this:
 
SDL_RenderCopy(renderer, textures[index], src, dst); 

or like this:
 
SDL_Texture *texture = textures[index];

1
2
//In render function:
SDL_RenderCopy(renderer, texture, src, dst);
Last edited on
I have a std::vector that stores textures.
This code implies that you don't have that. This code implies that you have a vector that stores pointers-to-textures.
SDL_Texture *texture = textures[index];



Would it be faster to create a reference or pointer to the texture and render using the reference


No, slower.

If you create a whole new pointer and set its value to be the same as a pointer in the vector, and use that new pointer, you've spent time creating a new pointer and setting its value.
Last edited on
> I was asking if I should render them like this:
> SDL_RenderCopy(renderer, textures[index], src, dst);

> or like this:
1
2
3
4
SDL_Texture *texture = textures[index];

//In render function:
SDL_RenderCopy(renderer, texture, src, dst);


Accessing the item in the vector once, storing the pointer, and using the stored pointer in the render function (which is called repeatedly) may be slightly faster. (This assumes that the same texture is rendered in all subsequent calls to the render function.) In practice, the performance difference would be negligible; the time taken to actually render the texture on the screen would dominate.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <vector>

struct texture { /*...*/ };
void render( const texture* ) ;

struct A
{
    A( std::vector<texture*>& textures, std::size_t pos ) 
        : textures(textures), pos(pos) { textures.at(pos) ; /* to validate pos */ }

    std::vector<texture*>& textures ;
    std::size_t pos ; // position of item to be rendered

    void render() const { ::render( textures[pos] ) ; }
};

struct B
{
    B( std::vector<texture*>& textures, std::size_t pos ) 
        : pointer( textures.at(pos) ) {} // store the pointer to the item

    texture* pointer ; // pointer to item to be rendered 

    void render() const { ::render(pointer) ; }
};

void foo( A& a ) 
{ 
    a.render() ; // access item using operator[] and render
    /*
        // x86-64, gcc, -O3
        mov     rax, QWORD PTR [rdi]
        mov     rdx, QWORD PTR [rdi+8]
        mov     rax, QWORD PTR [rax]
        mov     rdi, QWORD PTR [rax+rdx*8]
        jmp     render(texture const*)
    */
}

void bar( B& b ) 
{ 
    b.render() ; // render using stored pointer
    /*
        // x86-64, gcc, -O3
        mov     rdi, QWORD PTR [rdi]
        jmp     render(texture const*)    
    */
}

https://gcc.godbolt.org/z/wrzHGf
Topic archived. No new replies allowed.