Thread: Normal iterator pointer behavior

  1. #1
    Registered User
    Join Date
    Apr 2007
    Posts
    141

    Normal iterator pointer behavior

    I attempted to write a simple function that would apply an input function to all elements of an 'array'. The array is part of a complex class built to handle matrices from a third party. I had thought the normal behavior of the iterator is that derefence operator *iter can be used to both access and set the values of the underlying object. However this code leaves the original array (rm) unchanged.
    Code:
    /* apply a function to all elements of the array */
    void rapp2self(cvm::rmatrix &rm, double (*dfunc)(double))
    {
    	cvm::rmatrix::iterator q ;
    	for (q = rm.begin() ; q != rm.end() ; ++q) {
    		*q = (*dfunc) (*q) ;
    	}
    
    }
    The cvm library is an external matrix lib. that uses the std libraries to generate it's internal arrays (or so I thought). I suppose the *q itself could be overloaded here causing surprising results. I'm not even sure I have the source for the cvm library to check this. For a 'correctly' implemented iterator can I assume that I can assign to the object q points to via *q?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    For a 'correctly' implemented iterator can I assume that I can assign to the object q points to via *q?
    Yes, since iterators follow pointer semantics.

    Incidentally, have you considered using std::for_each or some other appropriate generic algorithm?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    If the code leaves the original array unchanged, then it seems that the iterators are not conforming. But you'd have to show the iterator code.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  4. #4
    Registered User
    Join Date
    Apr 2007
    Posts
    141
    Quote Originally Posted by laserlight View Post
    Yes, since iterators follow pointer semantics.

    Incidentally, have you considered using std::for_each or some other appropriate generic algorithm?
    I considered it, but my C++ reference made it look like more trouble than it was worth. I'll take a look at it again when I get a chance. Does it result in fewer characters type into my source code?

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Does it result in fewer characters type into my source code?
    In this case, I think it is likely, but that should not really be an important factor to begin with. If you are going to write a function to apply a function to the elements of a container, you might as well use a generic function that applies a function (or function object) to a range.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Incidently, your function is effectively for_each, except for the begin() and end() calls. So, it's a non-generic range version of for_each.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  7. #7
    Registered User
    Join Date
    Apr 2007
    Posts
    141
    Quote Originally Posted by laserlight View Post
    In this case, I think it is likely, but that should not really be an important factor to begin with. If you are going to write a function to apply a function to the elements of a container, you might as well use a generic function that applies a function (or function object) to a range.
    I agree with this wholeheartedly how does this work in C++?
    Is C++ so equipped with appropriate libraries?

    For example can I do something like this for some specially defined vectorized log function, or an overloaded log function?
    Code:
    std::vector<double> myvec ;
    ... code to initialize my vec ...
    
    std::vector<double>  logvec = log(myvec) ;
    That would be sweet. Come to think of it, it wouldn't be so hard to overload these functions now would it?

    By the way for some reason this code works just fine:
    Code:
    /* apply a function to all elements of the array  and
       return a copy of a new array */
    cvm::rmatrix &rapply(cvm::rmatrix &rm, double (*dfunc)(double))
    {
    	cvm::rmatrix::iterator q, i ;
    	cvm::rmatrix *x = new (GC) cvm::rmatrix(rm.msize(), rm.nsize()) ;
    	i = x->begin() ;
    	for (q = rm.begin() ; q != rm.end() ; ++q) {
    		*i = (*dfunc) (*q) ;
    		++i ;
    	}
    	return(*x) ;
    
    }
    So if I assign data via the pointer (i) to an allocated variable and return it. No problem. I could of course write vectorized versions of various functions via overloading, using this code as a template I suppose.

    However in the original case (rapp2self()) of passing an rmatrix by reference and trying to update it's values internally fails for some reason. I'll have to assume I'm doing something wrong, but the call I'm using to the rapp2self() function looks like this:

    Code:
    rapp2self(theta_nm_aoa, prin_value) ;
    where theta_nm_aoa is of type rmatrix. Not much to it really. Walking through the code with a debugger suggests internally that rapp2self is doing everything it's supposed to. It's only in the scope of the callee, where theta_nm_aoa remains unchanged. It's got to be something I'm doing that's stupid, but I haven't found it yet.

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    It's not always true that an iterator is assignable. For instance, std::map<K, V>::iterator is not assignable, even though it is non-const. However, i->second is assignable. See footnote [1] in http://www.sgi.com/tech/stl/Map.html

    However in this case, it seems like it makes sense to allow the assignment, so this was probably just an oversight on the part of the class designer.

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    I agree with this wholeheartedly how does this work in C++?
    Is C++ so equipped with appropriate libraries?

    For example can I do something like this for some specially defined vectorized log function, or an overloaded log function?
    Yes, with std::transform. Come to think of it, I think std::transform is more appropriate than std::for_each here.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Well, vectorized? Depends. GCC 4.3 has an experimental parallel implementation of some algorithms, using OpenMP. But for vectorization you'll have to rely on the compiler's loop unrolling. (No reason that wouldn't work, though, if the involved elements compile down well enough.)
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. cygwin sshd weird behavior
    By jEssYcAt in forum Tech Board
    Replies: 6
    Last Post: 05-19-2008, 02:05 PM
  2. inet_aton()... Noob needs help with sockets :|
    By Maz in forum C++ Programming
    Replies: 3
    Last Post: 11-22-2005, 04:33 PM
  3. HUGE fps jump
    By DavidP in forum Game Programming
    Replies: 23
    Last Post: 07-01-2004, 10:36 AM
  4. difference between register int and normal int
    By GanglyLamb in forum A Brief History of Cprogramming.com
    Replies: 6
    Last Post: 02-25-2003, 04:01 PM
  5. Game Design Topic #1 - AI Behavior
    By TechWins in forum Game Programming
    Replies: 13
    Last Post: 10-11-2002, 10:35 AM