C++ : returning references, and statics (2 in 1 :D)
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
C++ : returning references, and statics (2 in 1 :D)
Hi
I have currently a static function which returns a reference toward a vector, and I am wondering what happens with the allocated memory...
=> of course the vector is allocated dynamically so the reference is valid after the end of the function, but when I make "v = function(..)" what happens of the memory which contained v data before the call to this function ?? (as v now references the newly created vector).
In the end I'd like to know if some memory loss will occur or not ? And in this case is there a better way than passing the resultant vector as a parameter of the function and return void ??
===
I also have a question about static methods in a multithreaded environment : if I use static class attributes to be accessible from the static member function, is it any good ?? (aside from the fact it doesn't seem to work (why ? ), I am wondering if it would cause problems if 2 functions are called from 2 threads and manipulate the static attribute at the same time.... maybe that's why I can't seem to be able to use a static attribute in my static functions ? Or did I screw up elsewhere ?)
Thanks a lot for any hints ;p And I hope what I said was understandable
I have currently a static function which returns a reference toward a vector, ...
Hi Shautieh,
It would help to get a better picture of what you are trying to do. My questions are:
Is there a reason why you need to return a reference to a vector?
If you needed to change the type of the data member to a vector to, say, a list or some other data structure, won't you have to change the code that uses that class? This violates the idea of encapsulation, and is also very important when multiple threads are involved: you don't want to leave dangling references from the returned values from that static function.
When is the static data member initialized relative to the code that needs access to that data?
Same question as above, but for destruction. This is a common trap: Initialization of static data is not guaranteed by the language to be done in any particular order (especially if you have multiple translation units). Read up on the Singleton pattern (there are multiple approaches to Singleton too) to get a better grasp of the issues, especially when multi-threading is involved.
What is it you are trying to accomplish with the data being static?
Have you read Stroustrup's book, along with Scott Meyers "Effective" books? If not, spend some money and take the time to read them; it's time and money well spent since it covers a lot of these issues.
1. What do you mean ? I can't return a vector directly as it would take time to copy it
2. The function takes a vector as argument, so it is logical for it to return the same thing. Also, it will never be something else than a vector (except a C like array, but it is not a problem).
3. If I was to use static members, they would be initialized at the function call and reset at the end. In fact their only purpose would be to have less arguments passed to sub functions (I won't be using multi threading for this little project but was wondering if it would give problems if I had to use it)
4. destruction of the class ? There is nothing non static in it so it will never be instanciated. If you meant the destruction of the static attributes, they would get reinitialized on the next call of the static function I guess..
5. This maybe is the main problem. In fact I have a class which handles lots of things already, and I needed to add yet another functionality in this class => I could have added it directly, but I wanted to differentiate them more, so I created a class. As there is NOTHING to be kept between 2 calls of the main function of this class, I decided to disallow instanciation of this class, and make my functions statics.
I'd like to use some static class attributes in order to pass less arguments between this funtion and its subfunctions, and this is where I came to ask (because it doesn't seem to be possible, and if it was I'd like to know if it would make problems with several threads)... Yeah, it's almost a philosophic question (I am interested in the possible answers, but if you have a better/cuter idea than this "class with static functions" don't hesitate to notice me ;p)
6. Nop, what book from Stroustrup would you recommend ?
Can you post the function? Do you mean it's allocated with new? If so, it will just stay there until deleted, in which case you should return a pointer instead.
ta0kira
It is allocated with new, as otherwise the reference would refer to something which doesn't exist after the end of the function.
Here is what's of interest in the function :
Code:
vector<unsigned int> &FastTriangleReordering::tipsify(
const vector<unsigned int> &indexTab,
unsigned int numberOfVertices)
{
/*! O = we initialise the output index vector */
vector<unsigned int> *optimisedIndexTab = new vector<unsigned int>();
optimisedIndexTab->reserve(indexTab.size());
[...] // Here I put things in the optimisedIndexTab
return *optimisedIndexTab;
}
And I am wondering if, when faceArray is updated, its ancient values get deleted automatically or not ? A priori no if it was created dynamically but it's a problem if it is not...
Returning a pointer wouldn't change a thing here, right ?
This said, I thought about this function yesterday and in the end it will be better for it to take an array of unsigned int plus the size of this array instead of a vector, and thus return a pointer toward an unsigned int array, but I'll have this exact same problem of memory leak... any non intrusive idea ?
I don't understand why you want to alloc a new vector and return a ref to it if you are setting the orignal vector equal to the new vector. If you need to keep the orignal unoptmised index list then I would supply the out vector as a parameter, if you don't need it then change the input to non constant and update it. You can also return it if you want to use in an expression such as if( foo::tipsify(a,num).size() < orignal_size )...
Code:
typedef std::vector<unsigned int> vec_uint;
vec_uint &FastTriangleReordering::tipsify(vec_uint & indexTab, unsigned int numberOfVertices)
{
vec_unit temp(indexTab);//copy to work with
indexTab.clear();//see edit note at the bottom
[...] // Here put things in the IndexTab
return IndexTab;
}
[Edit note]
The following std::vector<T>::clear() is implementation defined on what it does. ie if it deallcoates memory or not- A common and defined trick that can be used is to call resize(0) which is garenteed not to deallocate the memory already allocated.
Last edited by dmail; 01-21-2008 at 08:59 AM.
Reason: added note about clear
Only the reference of the optimised vector is returned at the end of the function, as opposed to the whole vector to be copied. It is then copied into faceArray because it seems the operator= of the vector copies what's on its right instead of affecting its array to the new one and updating its size only... It would be cool to be able to do that, but is it possible ?
Quote:
Originally Posted by dmail
I don't understand why you want to alloc a new vector and return a ref to it if you are setting the orignal vector equal to the new vector. If you need to keep the orignal unoptmised index list then I would supply the out vector as a parameter, if you don't need it then change the input to non constant and update it. You can also return it if you want to use in an expression such as if( foo::tipsify(a,num).size() < orignal_size )...
Code:
typedef std::vector<unsigned int> vec_uint;
vec_uint &FastTriangleReordering::tipsify(vec_uint & indexTab, unsigned int numberOfVertices)
{
vec_unit temp(indexTab);//copy to work with
indexTab.clear();//see edit note at the bottom
[...] // Here put things in the IndexTab
return IndexTab;
}
[Edit note]
The following std::vector<T>::clear() is implementation defined on what it does. ie if it deallcoates memory or not- A common and defined trick that can be used is to call resize(0) which is garenteed not to deallocate the memory already allocated.
Well, most of the times the desired behavior is for tipsify to modify the "indexTab", but we thought it would be handier to allow for a different indexTab to receive the result... I am thinking of copying it locally in the function and modify the original now though...
If I do it like this I won't even need to clear its size as it will be the same as before in the end Resizing it to 0 will allow me to keep the push_back as it is though !
PS : as I said in my last post I am thinking of getting the indext tab as a int array, so I would have something like this now :
Code:
std::vector<unsigned int> indexTab;
// OR with Triangle being 3 unsigned int
std::vector<Triangle> indexTab;
// OR whatever that encapsulate an unsigned int array...
void FastTriangleReordering::tipsify(
unsigned int *indexTab,
unsigned int indexTabSize,
unsigned int numberOfVertices)
{
std::vector<unsigned int> temp(indexTab, indexTab + indexTabSize); //copy to work with
[...] // Here change indexTab directly
}
What do you think ? This will actually change the indexTab directly even if it was the tab that was internally kept inside the original indexTab vector without caring about its type, right ??
edit : it works like a charm this way ! And without being too ugly, me thinks
I would make the function take an additional vector <unsigned int>& argument to insert the modified list into:
Code:
void FastTriangleReordering::tipsify(
const vector<unsigned int> &indexTab,
unsigned int numberOfVertices, vector<unsigned int> &newTab)
{
newTab.reserve(indexTab.size());
[...] // Here I put things in the optimisedIndexTab
}
Yep, I think I would have done this in the end if I only had the problem of memory deallocation, but working with unsigned int array allows me to be way more generic in the end, as it can work with an unsigned int array as well as a vector of unsigned int, or a vector of structures composed of unsigned int !
It is for something 3D related too, so this trick isn't as bad as it seems (opengl functions work like that too, which made me think about this option to begin with )
... (opengl functions work like that too, which made me think about this option to begin with )
Now that OpenGL is in the picture: Have you searched on the web for pre-existing, open-source C++ libraries that "wrap" OpenGL that deal with these types of issues more effectively than creating it from scratch? Hmmm, I think that the Boost libraries would have algorithms that deal with the same, or similar, data structure issues here too (even though they will probably be not OpenGL-specific). Even if you choose not to use those libraries, reading through their code could give you some insights for your "small" project.
The other thing I noticed is the temporary being used inside that tipsify member function. You might measure to see if turning that temporary into a private data member would give you some performance benefit (measure, don't guess). The example I show below has that in mind.
http://www.cplusplus.com/reference/stl/vector/ states: "Just as regular arrays, vector containers have their elements stored in contiguous storage locations, which means that their elements can be accessed not only using iterators but also using offsets on regular pointers to elements." So, you can use a stl::vector of elements whose type is unsigned int, and also "pass" that to some (but probably not all) OpenGL functions. I believe this can be done by taking the address of the first element as the pointer to the C array of unsigned ints. For example, perhaps your FastTriangleReordering has a data-member that is of type std::vector<unsigned int>, and is used as follows:
Code:
class FastTriangleReordering
{
// constructors/destructors, and other methods elided for brevity here
private:
typedef std::vector<unsigned int> IndexTableType; // using a name such as vec_uint doesn't tell us anything useful
IndexTableType m_optimisedIndexTab; // internal storage buffer
};
void FastTriangleReordering::AddRawIndexTable(
const int * inIndexTable,
unsigned int numberOfVertices)
{
// Here I put things in the optimisedIndexTab, reserving as necessary, for the inIndexTable,
// using push_back or other methods, and that is all this method does.
// The idea here is to allow FastTriangleReordering to hold the internal index buffer for reuse by tipsify and draw methods.
}
void FastTriangleReordering::tipsify()
{
// Just do the operations to tipsify the table that is in m_optimisedIndexTab, and that is all (not returning
// the internal buffer at all). Grow or shrink m_optimizedIndexTab as necessary, hiding that detail from
// the code outside of FastTriangleReordering since it is an implementation detail.
}
void FastTriangleReordering::draw()
{
// Now just use the the tipsify-ed index table itself as if it is a C array of integers, when posting to the drawing engine (OpenGL, etc.)
// (The choice of tainting this class with OpenGL-specific calls is probably not a good idea, but that is a different issue):
IndexTableType::iterator first = m_optimizedIndexTab.front(); // or perhaps const_iterator is better depending upon the call to be made
unsigned int * c_array = &first; // may require a const_cast or some other call. I don't recall off hand.
// Now pass c_array to some drawing function, such as OpenGL:
gl_some_function(c_array, m_optimizedIndexTab.size()); // <-- an imaginary OpenGL function
}
Notice that I'm letting FastTriangleReordering do all of the dirty work, and it doesn't need to pass the array back to some other class. That doesn't, however, stop you from adding some function that returns the pointer to the first element, but then that defeats much of the purpose of an object-oriented design goals such as encapsulation and maintainability.
Now that OpenGL is in the picture: Have you searched on the web for pre-existing, open-source C++ libraries that "wrap" OpenGL that deal with these types of issues more effectively than creating it from scratch? Hmmm, I think that the Boost libraries would have algorithms that deal with the same, or similar, data structure issues here too (even though they will probably be not OpenGL-specific). Even if you choose not to use those libraries, reading through their code could give you some insights for your "small" project.
I must say I don't use Boost at all even though I heard a lot of good about it on several occasions. I really should go look in detail for what it has to offer one day (I am currently reading some of their stuff)
Quote:
Originally Posted by bgoodr
The other thing I noticed is the temporary being used inside that tipsify member function. You might measure to see if turning that temporary into a private data member would give you some performance benefit (measure, don't guess). The example I show below has that in mind.
I might measure it, but as it will never be the same between 2 call to the function I don't see how it could be more benefiting (it's only a guess as you said though). Even if the performances are similar, it is problematic to keep several MB of data for nothing, though I could use the 2 methods depending on some boolean if tipsify is to be called often or not. To be coherent I would have no statics anymore though, which I found handy Note : this array is NEVER going to be the same between 2 call to tipsify (tipsify is only called if there was some change), so keeping a copy of the array locally is not as interesting as it would have been otherwise (and I don't think I said it before ^^)
Quote:
Originally Posted by bgoodr
http://www.cplusplus.com/reference/stl/vector/ states: "Just as regular arrays, vector containers have their elements stored in contiguous storage locations, which means that their elements can be accessed not only using iterators but also using offsets on regular pointers to elements." So, you can use a stl::vector of elements whose type is unsigned int, and also "pass" that to some (but probably not all) OpenGL functions.
That is what I have been using indeed
I can't encapsulate this behavior though, as it heavily depends on how this vector is declared in the class which handles the mesh (called Mesh here), so it is its duty to call my funtion and give it the pointer to the first element of its array, and its size.
To sum it up, the tipsify method only takes this pointer, the size of the tab and some optional arguments and directly modify the data of this array. It returns nothing anymore and is, I think, totally transparent ^^
The caller doesn't know what's going on in this class except that it is going to change the data it wants to, so I think it is not too bad encapsulation wise
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.