LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 01-19-2008, 04:49 PM   #1
Shautieh
Member
 
Registered: Sep 2006
Distribution: Ubuntu
Posts: 64

Rep: Reputation: 15
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
 
Old 01-20-2008, 12:16 PM   #2
bgoodr
Member
 
Registered: Dec 2006
Location: Oregon
Distribution: RHEL[567] x86_64, Ubuntu 17.10 x86_64
Posts: 221

Rep: Reputation: 36
Talking

Quote:
Originally Posted by Shautieh View Post
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:
  1. Is there a reason why you need to return a reference to a vector?
  2. 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.
  3. When is the static data member initialized relative to the code that needs access to that data?
  4. 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.
  5. What is it you are trying to accomplish with the data being static?
  6. 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.
 
Old 01-20-2008, 01:14 PM   #3
Shautieh
Member
 
Registered: Sep 2006
Distribution: Ubuntu
Posts: 64

Original Poster
Rep: Reputation: 15
Hi

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 ?
 
Old 01-20-2008, 10:18 PM   #4
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
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
 
Old 01-21-2008, 06:33 AM   #5
Shautieh
Member
 
Registered: Sep 2006
Distribution: Ubuntu
Posts: 64

Original Poster
Rep: Reputation: 15
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;
}
It is meant to be used like this :
Code:
faceArray = FastTriangleReordering::tipsify(faceArray, vertices.size());
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 ?
 
Old 01-21-2008, 07:58 AM   #6
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
Quote:
1. What do you mean ? I can't return a vector directly as it would take time to copy it
What do you think the following snippet does?
Code:
faceArray = FastTriangleReordering::tipsify(faceArray, vertices.size());
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
 
Old 01-21-2008, 10:11 AM   #7
Shautieh
Member
 
Registered: Sep 2006
Distribution: Ubuntu
Posts: 64

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by dmail View Post
What do you think the following snippet does?
Code:
faceArray = FastTriangleReordering::tipsify(faceArray, vertices.size());
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 View Post
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

Last edited by Shautieh; 01-21-2008 at 06:02 PM.
 
Old 01-22-2008, 10:21 PM   #8
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
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
}
Code:
FastTriangleReordering::tipsify(faceArray, vertices.size(), faceArray);
ta0kira
 
Old 01-23-2008, 04:04 AM   #9
Shautieh
Member
 
Registered: Sep 2006
Distribution: Ubuntu
Posts: 64

Original Poster
Rep: Reputation: 15
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 )
 
Old 01-24-2008, 04:19 PM   #10
bgoodr
Member
 
Registered: Dec 2006
Location: Oregon
Distribution: RHEL[567] x86_64, Ubuntu 17.10 x86_64
Posts: 221

Rep: Reputation: 36
Quote:
Originally Posted by Shautieh View Post
... (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.

Oh, and by the Stroustrup book, I mean "The C++ Programming Language". See http://www.research.att.com/~bs/3rd.html

bgoodr
 
Old 01-25-2008, 10:27 AM   #11
Shautieh
Member
 
Registered: Sep 2006
Distribution: Ubuntu
Posts: 64

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by bgoodr View Post
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 View Post
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 View Post
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


Quote:
Originally Posted by bgoodr View Post
Oh, and by the Stroustrup book, I mean "The C++ Programming Language". See http://www.research.att.com/~bs/3rd.html

bgoodr
OK, I'll see if I can find it for a good price then.
Thanks a lot for your comments
 
Old 01-26-2008, 11:32 AM   #12
bgoodr
Member
 
Registered: Dec 2006
Location: Oregon
Distribution: RHEL[567] x86_64, Ubuntu 17.10 x86_64
Posts: 221

Rep: Reputation: 36
Quote:
Originally Posted by Shautieh View Post
Thanks a lot for your comments
You are most welcome!

bgoodr
 
  


Reply

Tags
reference, static



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Good References GuodMan Solaris / OpenSolaris 6 03-15-2006 08:31 PM
shell references nariman Linux - Newbie 3 02-25-2006 05:36 AM
??Good C References Please?? InvisibleSniper Programming 9 10-28-2005 01:45 PM
references jenny_psion Programming 0 08-12-2003 03:06 AM
references to other other sites pbharris LQ Suggestions & Feedback 10 04-10-2002 10:20 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 08:08 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration