CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11
  1. #1
    Join Date
    Oct 2006
    Posts
    4

    passing vector by reference

    I have a winapi where I try to pass a reference of a vector (but it is not as simple vector as in the tutorials or examples) to function but can not get it together...

    I have a Gui. If a certain button is clicked it will initiate EnumProc. I would like to pass a reference of an empty vector in the additional LPARAM of EnumProc. If windows of my criteria are found under the EnumProc i would put the handle, name of the window and some other stuff in the vector. They would then be accessible when the EnumProc has ended...

    Currently when Compiling i'm getting:
    expected primary-expression before "arMyClass"
    at the line where EnumProc is being called (2nd bolded line)

    I tried to bold the parts that I think/know are causing this. Any help appreciated.

    Code:
    .
    .
    .
    class CMyClass
    {
    public:
      CMyClass() {}
      CMyClass(int def_x, int def_y, string def_nimi, HWND def_handu) : x(def_x), y(def_y), nimi(def_nimi), handu(def_handu) {}
      virtual ~CMyClass() {}
      int x, y;
      string nimi;
      HWND handu;
    };
    
    BOOL CALLBACK EnumProc(HWND thwnd,vector<CMyClass*> &v);
    HINSTANCE hInstance;
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
    .
    .
    .
    }
    
    LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) 
    {
    .
    .
    .
    case WM_COMMAND : 
    .
    .
    .
     case BN_CLICKED:
    .
    .
    .
    if ( LOWORD (wParam) == 6 ) {
    vector<CMyClass*> arMyClass;
    
    //testing if it works, adding some stuff
    arMyClass.push_back(new CMyClass(2, 40, "kasdsdlle", NULL));
    arMyClass.push_back(new CMyClass(4, 60, "visdsadlle", NULL));
    
    EnumWindows((WNDENUMPROC) EnumProc,vector<CMyClass*> arMyClass);
    .
    .
    .
    }
    
    .
    .
    .
    }
    
    BOOL CALLBACK EnumProc(HWND thwnd,vector<CMyClass*> l)
    {
    //THESE LINES JUST FOR TESTING
    //testing if I can access the vector here
    vector<CMyClass*>::iterator itPos = l.begin();
    for(; itPos < l.end(); itPos++) {
          string teksti = (*itPos)->nimi;
          char *p;
          p=&teksti[0];
          MessageBox(NULL, p, "otsikko", MB_OK);
    }
    //End of test lines
    
    char buff[MAX_PATH+1];
    GetWindowText(thwnd,buff,MAX_PATH+1);
    if(strstr(buff, myCriteria)) {
    //adding to the vector
    l.push_back(new CMyClass(2, 40, "third", NULL));
    }
    
    return TRUE;
    }

  2. #2
    Join Date
    Feb 2005
    Location
    Normandy in France
    Posts
    4,590

    Re: passing vector by reference

    First bug (the one which implies a syntax error): You can't define a new variable inside an expression (BTW, you would not be able to access the variable in following statements):
    Code:
    EnumWindows((WNDENUMPROC) EnumProc,vector<CMyClass*> arMyClass);
    It should be:
    Code:
    vector<CMyClass*> arMyClass;
    EnumWindows(EnumProc,reinterpret_cast<LPARAM>(&arMyClass));
    Second bug: You don't declare EnumProc with the correct prototype. Behavior is undefined for the C++ standard, even though with the current Win32 CALLBACK calling convention, it's likely to not work too bad.
    Moreover, you define EnumProc with a value vector<CMyClass*> parameter (you forgot the & character).

    If you want to avoid calling conventions issues under Win64, you should respect the prototype:
    Code:
    BOOL CALLBACK EnumProc(HWND thwnd,LPARAM); // declaration
    Code:
    BOOL CALLBACK EnumProc(HWND thwnd,LPARAM lParam) { // definition
      vector<CMyClass*> &l=*reinterpret_cast<vector<CMyClass*>*>(lParam);
      // your code
    }
    Do you really need a dynamic allocation for CMyClass objects? Would not a vector<CMyClass> work as well?
    Why does CMyClass have a virtual destructor? It has no other virtual function. Do you derive from it?
    "inherit to be reused by code that uses the base class, not to reuse base class code", Sutter and Alexandrescu, C++ Coding Standards.
    Club of lovers of the C++ typecasts cute syntax: Only recorded member.

    Out of memory happens! Handle it properly!
    Say no to g_new()!

  3. #3
    Join Date
    Oct 2006
    Posts
    4

    Re: passing vector by reference

    First of all thank you for the time you took to answer my question.

    As you propably noticed I'm quite new to C++ and I had copied most of the code from different examples, sources and tutorials (that seems like the most motivating way for me to learn something new when I can experiment something at the same time).

    At the time of posting my question I had already tried several approaches to get it working. That's why some of the lines didn't make any sense anymore...

    As to your answer I got it all working now, I also took your advice and removed the virtual destructor and dynamic allocation for CMyClass objects.

    Thanks again.

  4. #4
    Join Date
    Oct 2005
    Location
    Norway
    Posts
    120

    Re: passing vector by reference

    Quote Originally Posted by SuperKoko
    Do you really need a dynamic allocation for CMyClass objects? Would not a vector<CMyClass> work as well?
    Why does CMyClass have a virtual destructor? It has no other virtual function. Do you derive from it?

    Uhm, a vector of any object containing more than just a couple of members is going to start smelling like visual basic. You do not want objects inside vectors or ANY of the STL containers. For just about every operation performed with any of the standard containers, behind the scenes, you'll be pushing the use of assignment operator and copy constructor to such an extent that your code will be sub par to put it mildly.

    It simply costs too much, and is bad programming practice - mind you, for very small class objects, I wouldn't mind putting them on the stack tho.

    As for virtual destructors, I do agree with you to a certain extent. I bet the class object was created in MSVC++, using "create new class" wizard. that usually gives you a virtual destructor right there. Performancewise, it's not really a performance hit, and in Strousrup's spirit, "Every problem can be solved by adding another level of indirection", you should be prepared to see your objects suddenly deriving, or being derived from other objects. It can happen, doesen't hurt too much, so I'd call it an "OK" programming practice.

  5. #5
    Join Date
    Feb 2002
    Posts
    4,640

    Re: passing vector by reference

    Quote Originally Posted by Efitap
    Uhm, a vector of any object containing more than just a couple of members is going to start smelling like visual basic. You do not want objects inside vectors or ANY of the STL containers. For just about every operation performed with any of the standard containers, behind the scenes, you'll be pushing the use of assignment operator and copy constructor to such an extent that your code will be sub par to put it mildly.

    It simply costs too much, and is bad programming practice - mind you, for very small class objects, I wouldn't mind putting them on the stack tho.

    As for virtual destructors, I do agree with you to a certain extent. I bet the class object was created in MSVC++, using "create new class" wizard. that usually gives you a virtual destructor right there. Performancewise, it's not really a performance hit, and in Strousrup's spirit, "Every problem can be solved by adding another level of indirection", you should be prepared to see your objects suddenly deriving, or being derived from other objects. It can happen, doesen't hurt too much, so I'd call it an "OK" programming practice.
    Why? I think it's wrong to make general statements like this. Every situation is different. Code first for solving the problem, then optimize.

    Viggy

  6. #6
    Join Date
    Oct 2005
    Location
    Norway
    Posts
    120

    Re: passing vector by reference

    Quote Originally Posted by MrViggy
    Why? I think it's wrong to make general statements like this. Every situation is different. Code first for solving the problem, then optimize.

    Viggy
    When working with STL containers, the general statement is already spelled out in it's documentation. I've heard collegues joke about calling it the standard copy library

    It is not totally unrelated to the fact that any object living inside an STL container has to be canonical (I've heard the term "nice" used too, that means, in order to expect sane behaviour from an stl container, you'll have to implement a copy operator, a copy constructor, a destructor, as well as a less-than operator, should you want to sort any of the items.

    For every insert, copy, sort operation, etc, each element in an STL container will be copied and then deleted. That's alot of allocation / deallocation for a class object, unless it is the same size as the pointer to it (int).

    Consider a class with only 3 interger members named C3Int. Let us assume it is canonical, and ready for use in a stl container. If I am passing objects from the stack to it, instead of using pointers to objects, the container itself will take 3 times as long for every operation I do, such as Insert or sort, assuming that the int data type is the same size as the int* (today, that's usualyl true). Say my vector contains 100 pointers to elements. It will take 100 copy operations to copy this vector.

    If the vector contains 100 stack allocated elements (non-pointers), the same copy operation will now take 300 copy operations. Worse even, if your copy constructor or assignment operator aren't coded inline because you either forgot to, or the optimizer didn't figure it out, you're looking up a pointer to the assignment operator for each operation. Is the foul stench of VB coding reaching you yet?

    I do not wish to offend anyone, but in my humble opinion, C++ is all about speed. For convenience and learning, you have a ton of alternatives, all better than C++. What you gain with C++ is the execution speed and the proximity to the CPU itself. And for that very reason, I believe that teaching people stl the wrong way, is a bad, bad thing. very rarely do you want to put anything else than pointers inside stl containers. In fact, the only situation that springs to mind is, for example, if you're wrapping an SDK written in plain ol' C that pushes arrays back and forth alot.

    I do agree that every situation is different. But just as you always canonize your class objects, even though you don't need to, it is not the worst practice to also implement a virtual destructor. Better to pick up that habit, than NOT picking it up - debugging missing destructor problems in deep inheritance trees is just not fun, and totally not worth it when the simple solution is just to virtualize the destructor

  7. #7
    Join Date
    Feb 2002
    Posts
    4,640

    Re: passing vector by reference

    Nope. You're example is flawed. Modern compilers are quite smart, and I think that copying 3 ints will take the same amount of time as copying 2 or 4. In other words, the compilers are smart enough to optimize a lot of this "copying". Which is why I said that I don't like generalizations like this. Code first, optimize later. We're not working with tube computers and punch cards anymore.

    Viggy

  8. #8
    Join Date
    Oct 2005
    Location
    Norway
    Posts
    120

    Re: passing vector by reference

    Quote Originally Posted by MrViggy
    Nope. You're example is flawed. Modern compilers are quite smart, and I think that copying 3 ints will take the same amount of time as copying 2 or 4. In other words, the compilers are smart enough to optimize a lot of this "copying". Which is why I said that I don't like generalizations like this. Code first, optimize later. We're not working with tube computers and punch cards anymore.

    Viggy
    I fail to see how my compiler would optimize away even the stupidest of classes for copy operations.. The 3 ints was an example, making the point that anything the compiler has to copy that is larger than an int, is going to hurt performance.

    Either you know something about compilers that has eluded me for the last 15 years, or you're just giving today's compilers more credit than they deserve. I'd love to be wrong, so, please prove it for me.

  9. #9
    Join Date
    Aug 1999
    Posts
    586

    Re: passing vector by reference

    Quote Originally Posted by Efitap
    I fail to see how my compiler would optimize away even the stupidest of classes for copy operations.. The 3 ints was an example, making the point that anything the compiler has to copy that is larger than an int, is going to hurt performance.

    Either you know something about compilers that has eluded me for the last 15 years, or you're just giving today's compilers more credit than they deserve. I'd love to be wrong, so, please prove it for me.
    On my relatively modest 2.4 MHz machine, I can load a "std::vector" with a 100 "std:string" objects and then copy it a million times in about 7 seconds. For the vast majority of programs with far more modest requirements, processing time simply isn't an issue.

  10. #10
    Join Date
    Feb 2005
    Location
    "The Capital"
    Posts
    5,306

    Re: passing vector by reference

    Quote Originally Posted by Efitap
    When working with STL containers, the general statement is already spelled out in it's documentation. I've heard collegues joke about calling it the standard copy library
    I did not read any further of your post. Probably, your colleagues don't know how to work with the STL containers. They don't know how to prevent copying. They don't know what references are, if vector has a member function reserve or if vector is the right container choice they made. There are many ocassions where people wrongly choose std::vector where they should have had actually chosen std:eque.

    Okay, I read a bit further and you have a lot of misconceptions. You give the example of sorting. Sorting a vector of plain objects is not at all going to be slower than sorting a vector of pointer to those objects. In fact, it will lead to many bugs if you do not write a predicate to dereference the pointers and do the comparison.

    Moreover, if it is sorting that is the primary goal of the container to be, then you would be better placed in using an std::set. This may depend on many other design considerations too.
    Last edited by exterminator; November 4th, 2006 at 01:21 PM.

  11. #11
    Join Date
    Oct 2005
    Location
    Norway
    Posts
    120

    Re: passing vector by reference

    Quote Originally Posted by exterminator
    I did not read any further of your post. Probably, your colleagues don't know how to work with the STL containers. They don't know how to prevent copying. They don't know what references are, if vector has a member function reserve or if vector is the right container choice they made. There are many ocassions where people wrongly choose std::vector where they should have had actually chosen std:eque.
    You can't prevent copying in STL during any operation that will modify the contents of an STL container, no matter which one you're talking about, the nodes will be copied, invoking both a destructor and a copy constructor, if you're working with containers of objects. The choice of container type is not an issue in this post, and keep the insults to yourself.

    Okay, I read a bit further and you have a lot of misconceptions. You give the example of sorting. Sorting a vector of plain objects is not at all going to be slower than sorting a vector of pointer to those objects. In fact, it will lead to many bugs if you do not write a predicate to dereference the pointers and do the comparison.
    I will give you no arguments about predicates, however, you are wrong in thinking that sorting a vector of references is as slow/fast as sorting a vector of objects. STL never moves objects, it copies them. Copying a pointer is less work than invoking the object's copy constructor. Again, STL containers copy, copy and copy. Learn this, write it in the roof of your bedroom, and fall asleep looking at it every night until it sticks. Copying an object means that you're invoking a destructor as well as a copy constructor. Copying a pointer means copying "just" a pointer.


    Moreover, if it is sorting that is the primary goal of the container to be, then you would be better placed in using an std::set. This may depend on many other design considerations too.
    You are right, but this is not the topic of the conversation.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured