[aspectc-user] overloaded operator ++() and ++(int)

Olaf Spinczyk Olaf.Spinczyk at informatik.uni-erlangen.de
Tue May 24 12:04:20 CEST 2005


Hi Hans,

Hans VB wrote:
> Hey,
> 
> it seems to work if i use execution in stead of call (maybe because i am 
> in main()), so ok...
> 
> What bothers me now is the following :
> I want to select all constructions of objects of class B but not those 
> that happen in/caused by operators.
> this is my operator ++(int) :
> 
> B operator ++(int) {
>    B tmp = *this;
>    ++(*this);
>    return tmp;
> }
> 
> This doesnt return a reference because you'd better not return reference 
> of local temp vars. What it does do is call a constructor when it 
> returns tmp.
> I manage to filter out the construction of tmp, but not the one of this 
> returned tmp :
> 
> pointcut allRealConstructions() = construction("B") && !cflow( 
> execution("% B::operator %(...)") );
> 
> Any ideas would be greatly appreciated! (and quite urgently too - this 
> is in fact for my thesis which has to be finished real soon ;-)
> 
> Greets,
> Hans

the problem with cflow and the construction of the result object is that 
the creation of a copy of the result object is (1) a client-side 
activity and, thus, not in the cflow of your operator++. Furthermore, 
(2) the compiler is allowed to avoid the execution of the copy 
constructor. This is illustrated by the following example:

---
#include <iostream>
using namespace std;

class B {
public:
   B() {
     cout << "B()" << endl;
   }
   B (const B&) {
     cout << "B(const B&)" << endl;
   }
   B& operator = (const B&) {
     cout << "operator = (const B&)" << endl;
   }
};

B f () {
   B tmp;
   return tmp;
}

void g (const B& b) {}

int main () {
   f ();
   B result = f (); // no copy constructor executed!
   g (f()); // no copy constructor executed!
   B x (result); // here the object is created with the copy constructor
}
---

If you compile it with g++ 3.3 the output is:

B()
B()
B()
B(const B&)

Although f() is much like your operator ++ the copy constructor is never 
executed.

To summarize: It is (1) not guaranteed that the copy constructor will be 
  executed. If it is executed, the execution is not in the cflow of your 
operator++ (2).

Now AspectC++ come into play: If you weave execution advice for the 
operator ++ the generated wrapper function will allocate memory space 
for the result object and initialize it with the result of the orginal 
(wrapped) function by using the copy constructor. This copy construction 
can't be avoided by compiler optimizations. This copy constructor 
execution is *in* the cflow! However, this temporary result object is 
then return by the wrapper function to the caller, which might again 
result in a copy constructor execution. This (second) copy construction 
is not in the cflow! That's how it is currently implemented. Can you 
confirm that the copy constructor is executed twice in your code?

 From the language point of view I would prefer the copy construction of 
the result object to be in the cflow of the call, but not in the cflow 
of the execution. This brings us back to the problem with call advice 
for operator ++(int) :-(. I think it would be best to with fixing the 
call advice problem. Do you agree?

Best regards,

Olaf



More information about the aspectc-user mailing list