[C++] Question about memset

Started by
8 comments, last by Fruny 15 years ago
Hi all! I have a question about memset as I am unsure of how to apply it in my program. I have the following line in my function:

 memset(&m_heights[0], 0, m_heights.size());
I save m_heights value into a vector container. Now, let's say I need to make a copy of this value(s) and also create another set of values in memory after copying, how should I implement it? is it something like

memset(&m_heightsCopy[0], m_heights.size(), m_heightsCopy.size()); // copy of m_heights
memset(&m_heights2[0], m_heightsCopy.size(), m_heights2.size()); //new vector
Also, is it necessary to destroy values created on program exit? Thanks for any help offered on this!
Advertisement
Why are you using memset() on a standard container? Copying a vector is a lot easier than you are making it:
std::vector<int> vec;// fill a vector with zerosstd::fill(vec.begin(), vec.end(), 0);// copy a vectorstd::vector<int> copy = vec;// create another set of values in memorystd::vector<int> anotherSetOfValues;

You probably don't need to use memset() (or memcpy()) in modern C++.
In C++ you probably shouldn't be using memset at all.

#include <algorithm>...std::fill(m_heights.begin(), m_heights.end(), 0);


It is actually possible that this will be implemented in terms of memset (but then m_heights must contain character types).
If you're using C++ rather than C, do not use memset or memcpy.
Use std::fill, std::fill_n or std::copy instead, they do the Right Thing.

#include <algorithm>std::fill(m_heights.begin(), m_heights.end(), 0);


Quote:Now, let's say I need to make a copy of this value(s) and also create another set of values in memory after copying, how should I implement it?


m_heightsCopy = m_heights;m_heights2 = m_heightsCopy;


Quote:Also, is it necessary to destroy values created on program exit?

Only if you used new somewhere.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Thanks all for the reply!

This is actually the full function:
bool HeightMap::Init(int size, int gridSpacing, float scale){    m_heightScale = scale;    m_size = size;    m_gridSpacing = gridSpacing;    try    {        m_heights.resize(m_size * m_size);    }    catch (const std::bad_alloc &)    {        return false;    }    memset(&m_heights[0], 0, m_heights.size());    return true;}


m_heights will then be filled in another function :
void HeightMap::createFractaltype(float roughness){    srand(static_cast<unsigned int>(time(0)));    std::fill(m_heights.begin(), m_heights.end(), 0.0f);    int p1, p2, p3, p4, mid;    float dH = m_size * 0.5f;    float dHFactor = powf(2.0f, -roughness);    float minH = 0.0f, maxH = 0.0f;    for (int w = m_size; w > 0; dH *= dHFactor, w /= 2)    {        // Diamond Step.        for (int z = 0; z < m_size; z += w)        {            for (int x = 0; x < m_size; x += w)            {                p1 = heightIndexAt(x, z);                p2 = heightIndexAt(x + w, z);                p3 = heightIndexAt(x + w, z + w);                p4 = heightIndexAt(x, z + w);                mid = heightIndexAt(x + w / 2, z + w / 2);                m_heights[mid] = Math::random(-dH, dH) + (m_heights[p1] +    m_heights[p2] + m_heights[p3] + m_heights[p4]) * 0.25f;//etc


Isn't using memset the only way in this application?

edit: To make things clearer I need to store m_heights value when I call this function once into a temp vector (lets say v_temp1)and then call this function the second time and store it in the other vector (v_temp2). I would then need to interpolate between these two vector values.

Pretty tired at the moment so sorry if I am sounding incoherent and asking silly questions! Thanks!
Quote:Original post by jonathanc
m_heights.resize(m_size * m_size);
...
memset(&m_heights[0], 0, m_heights.size());

The elements in a vector (I assume it is a vector) are default-initialized. They will already be zero, no need for a memset. Furthermore, the problem with memset is that it does treat memory as byte data. std::fill and std::fill_n treat memory as whatever data type your pointer points to.

Quote:m_heights will then be filled in another function

If you're going to do a fill anyway, why bother with the first one?


Quote:Isn't using memset the only way in this application?

It never is the only way.

"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan

Hi! Wow thanks for the quick replies!

Quote:Original post by Fruny

The elements in a vector (I assume it is a vector) are default-initialized. They will already be zero, no need for a memset. Furthermore, the problem with memset is that it does treat memory as byte data. std::fill and std::fill_n treat memory as whatever data type your pointer points to.


Yes , m_height's type is std::vector <float>. So you say its ok just to do
 m_heights.resize(m_size * m_size);
without the need to copy it into memory? (I am also working in OpenGL here hence the slight confusion)

Quote:
If you're going to do a fill anyway, why bother with the first one?

Whoops, I think I might have been unclear with my statement. Sorry. What I want to do is initialize m_heights to a certain size. Then another function will access m_heights (which is global to the class) and fill it with values.

Another function will access m_heights again. This function will access createFractaltype twice. Twice because I use the values for interpolation. Hence why I need 2 copies (tempA and tempB). I want to interpolate from one set of values to another so the rendering will appear to "morph" from one mesh to another.

I am still new to C++ (from C) so I guess some concepts still new to me.
Quote:Original post by jonathanc
Yes , m_height's type is std::vector <float>. So you say its ok just to do
 m_heights.resize(m_size * m_size);
without the need to copy it into memory? (I am also working in OpenGL here hence the slight confusion)


Yes. std::vector::resize() does change the number of elements in the vector. When you increase that number, the new elements will be initialized to the default value for that type. For float, as well as other basic types, that is the value 0.

Container elements are always initialized. They are not like data in C arrays.

Quote:I am still new to C++ (from C) so I guess some concepts still new to me.

I strongly suggest you start by spending a bit of time studying the functionality exposed by std::vector's member functions (there are other containers, but vector is the easiest to deal with). Then have a quick look over what's available in the <algorithm> header (it helps to have some Computer Science grounding).

If you want to exchange the contents of two vectors, note the presence of the std::vector::swap() member functions which obviates the need to use a temporary variable. That can be important for performance.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Thanks! You have indeed helped a lot. Will go look more into standard vectors.

Quote:Original post by jonathanc
Thanks! You have indeed helped a lot. Will go look more into standard vectors.


Just keep in mind that there are other containers, with different trade-offs than vector. Using the right data structure and the right algorithms is key to having good performance (along with not doing unnecessary work ;))
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan

This topic is closed to new replies.

Advertisement