c++ performance question

CU

Platinum Member
Aug 14, 2000
2,415
51
91
I ran across some code that did something like this. I can see where obj.method().method().method(); might be quicker to type and even read depending on what obj might look like typed out. But wouldn't it be faster to not have method() return a reference to the object and just type out obj. each time you call the method, or does the compiler optimize that out? I had never seen it done this way before and it threw me for a loop before I realized what method() returned, especially with it written down instead of across like in my example below.

Example:

class test
{
public:
test():x(0){}
test& add(int i) {x+=i; return *this;}
int x;
};

int main()
{
test t;
t.add(1)
.add(2)
.add(3);

return 1;
}

PS. What is the syntax to put the code in code blocks?
 

Cogman

Lifer
Sep 19, 2000
10,286
145
106
code block syntax is [ code ] [ / code ] Without the spaces.

the #1 rule of optimization is to NEVER assume something is faster without testing (or a high level of understanding of the assembly).

From the way you have it written, I don't see any benefit to rewriting the code. This should work and be pretty well optimized by the compiler. (What you are suggesting doesn't seem like it would result in any sort of different underlying assembly)

Though, if you want faster, and you are going to be calling the same function over and over, then a better bet is to pass in an array with all the items you need to do things to to the object, that would eliminate some of the overhead of function calling.
 

Schmide

Diamond Member
Mar 7, 2002
5,745
1,036
126
You could just overload it and use the inline directive, if the compiler can inline it it will be the same as if you inserted the code there.

Code:
class test {
 public:
   int m_iData;
   test &operator+=(test&);     
   int operator+(int);     
 };
 
 inline test &test::operator+= (test &cTest)
 {
     m_iData+=cTest.m_iData;
     return *this;
 }
 inline int test::operator+ (int iInput)
 {
     return m_iData+iInput;;
 }
 

Cogman

Lifer
Sep 19, 2000
10,286
145
106
You could just overload it and use the inline directive, if the compiler can inline it it will be the same as if you inserted the code there.

Code:
class test {
 public:
   int m_iData;
   test &operator+=(test&);     
   int operator+(int);     
 };
 
 inline test &test::operator+= (test &cTest)
 {
     m_iData+=cTest.m_iData;
     return *this;
 }
 inline int test::operator+ (int iInput)
 {
     return m_iData+iInput;;
 }
Generally you should avoid doing declared inlines. Most modern compilers know how to do that just fine. Inlining can even make the program slower.
 

Net

Golden Member
Aug 30, 2003
1,592
3
81
there isn't a black and white answer. depends on what you are doing, what your using it for, etc...

things to keep in mind. there are a lot of scenarios where you will want your objects to contain objects and those objects contain objects. you'll want to access those objects by getters that return a reference to those objects.

the compiler isn't that smart. there are scenario's where it won't know what that reference is pointing to until run-time. To get a feel for those scenarios read polymorphism, virtual functions, dynamic binding, etc... Also read <static_cast> and <dynamic_cast>

if your code is calling
obj.getMethod1().getMethod2().getMethod3().getRun()
obj.getMethod1().getMethod2().getMethod3().setBlah()
etc...

Then its a good canidate to refactor to:

MyType foo = obj.getMethod1().getMethod2().getMethod3();
foo.getRun();
foo.setBlah();

a good book to read is Refactoring: Improving the Design of Existing Code by Martin Fowler and Code Complete 2.

In short you have to look at the situation to determine the best answer.
 
Last edited:

Schmide

Diamond Member
Mar 7, 2002
5,745
1,036
126
It's just a directive, the compiler still makes the final decision. You certainly shouldn't inline anything complex and most compilers won't allow that anyways. The above code would probably be inlined anyways. Reality is when you're talking operations this simple, any optimization/directive would make little if any difference.

My code rule - usually 10&#37; of your code takes 90% of the execution time, so optimize wisely.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
If its in the header, its a potential candidate for inlining among most compilers.

Ergo:
Code:
class MyThing {
public:
  void Set(int x) { m_x = x; }
private;
  int m_x;
};
Is just as fast as:
Code:
class MyThing {
public:
  int m_x;
};
...
p_thing->m_x = x;

I hear that some IDEs will inline C++ even when the target method is in a source file... thats black magic as far as the C++ ABI is concerned, so don't assume it.

But if x.Method1().Method2() uses only header-defined methods, go for it!

Bonus extra response:
I've also seen this sort of thing in headers, which is a helluva lot more verbose and slightly more readable:
Code:
class MyThing {
public:
  void Set(int x);
private:
  int m_x;
};

extern inline MyThing::Set(int x) {
  m_x = x;
}
 

CU

Platinum Member
Aug 14, 2000
2,415
51
91
Naturally, neither the obj or the method called where simple like my example. The method was actually templated in the case I saw. The point was will the compiler see that *this doesn't need to be done nor does returning it. Because the object is already there as "t" in my example.

Which is faster or more readable for that matter?
Code:
t.add();
t.add();
t.add();

Code:
t.add()
.add()
.add();

I believe the first is more readable and maybe faster because you don't have to do *this. And yes I know this is not going to make any real speed difference. Just more of a curiosity.
 

Cogman

Lifer
Sep 19, 2000
10,286
145
106
Naturally, neither the obj or the method called where simple like my example. The method was actually templated in the case I saw. The point was will the compiler see that *this doesn't need to be done nor does returning it. Because the object is already there as "t" in my example.

Which is faster or more readable for that matter?
Code:
t.add();
t.add();
t.add();

Code:
t.add()
.add()
.add();

I believe the first is more readable and maybe faster because you don't have to do *this. And yes I know this is not going to make any real speed difference. Just more of a curiosity.

They should both translate into exactly the same code. (I mean, EXACTLY). As for readability, I prefer #1.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
They should both translate into exactly the same code. (I mean, EXACTLY). As for readability, I prefer #1.
Agreed. If the methods are sitting in headers (as templates are), then they will become the same code.
 

Net

Golden Member
Aug 30, 2003
1,592
3
81
i prefer the first one generally. if i'm adding like we are here, definately the first one.

i prefer the second one for some variations of the builder pattern, NutritionFacts.Builder(110, 5).calories(50).sodium(35).carbohydrate(25).build();