开发者

Temporaries in member functions - C++

开发者 https://www.devze.com 2023-02-01 04:24 出处:网络
After putting some code to work, I\'m trying to optimize it. One thing that I\'m trying to avoid is the creation of temporaries. Given a class

After putting some code to work, I'm trying to optimize it. One thing that I'm trying to avoid is the creation of temporaries. Given a class

class foo{
   private:
     int a;
   public:
     foo(int sa):a(sa);
     ~foo(){}
    inline int multiply(int b) {return a*b;}//temporary?
};

The intel compiler is giving me the temporary created/reference temporary used here. Is any temporary variable being created?

EDIT: edited the return type. Also, I think that no temporary variable is being created in multiply, but the intel compiler gives me an error about that.

EDIT 2: After the requests below, here is a FULL code that the intel compiler v. 12 gives the error:

 #include <iostream>
 #include <complex>

 using namespace std;
 const double pi = 3.1415;
 const complex <double> I = (0.0,I);
 const complex <double> oneover2piI = (1.0 / (2.0 * pi * I));

  class foo{
     private:
       complex <double> a;
     public:
       foo(complex <double> sa):a(sa){}
       ~foo(){}
       inline complex <double> multiply(complex<double> b) 
       {return  a*sqrt(b);}
   };

The compilation line is

  icc -g -O2 -w2 -debug parallel -Wcheck -Weffc++ -mp -fp-stack-check -wd981 -wd2015 -wd1418  test.cpp -o  test

And the resulting warning is

  test.cpp(7): remark #383: value copied to temporary, refer开发者_高级运维ence to temporary used
  const complex <double> oneover2piI = (1.0 / (2.0 * pi * I));
                                         ^

The question was to understand what the compiler is balking at, and not to be hanous.

Thanks!


Don't worry about it.

What you are doing is called "premature micro-optimization," and it is the root of much evil.

It is also largely futile to try to micro-optimize

  1. micro-optimization without first profiling your code and identifying the places that need to be optimized is a complete waste of time. You might end up shaving picoseconds off a routine that takes millions of picoseconds. Why bother?

  2. The compiler will optimize you code far better than you can. MicroSoft for example has a team of people whose only job is to work on the optimizer. They are very smart people, working all day every day finding ways to optimize your code. In this case, the temporaries will often be optimized away. Let them do their thing. They are better at it than you.

  3. micro-optimizations often come at the cost of harder to understand code. Code that is harder to understand is much more prone to having defects. Those 4 picoseconds you saved are worthless if your function returns "fA@#zzzzzzz" instead of "foo".

First, select the correct algorithms for your task. Then write good, robust code that implements those algorithms. Profile in release mode second. Guided by the profiler, find the places that really need to be optimized, if there are any. Then optimize.


I think the compiler issues a warning because it translates:

const complex <double> oneover2piI = (1.0 / (2.0 * pi * I));

to invoke a default copy constructor:

Object::complex<double>(const complex<double>&)

which takes a reference of the temporary object as the argument, and makes a shallow copy (that results in data sharing if you use pointers) of the object. Basically this data sharing + temporary lifespan is the core of the problem. Take a look at the "academic" class below.

#include<iostream>

class A
{

public:

  A()
    :attribute(new char[10]) {}

  ~A()
  {
    std::cout << "d'ctor" << std::endl; 
    if(attribute){
      delete [] attribute;
      attribute = 0;
    }
  }

  A& operator +(const char& n)
  {
    //do some operation
    return *this;
  }

  void reset_attribute(char *new_ptr)
  {
    attribute = new_ptr;
  }

private:

  char *attribute;
};

int main()
{
  {//new scope to invoke destructors
    A b;
    A c = b;
    b.reset_attribute(new char[10]);
  }//no problem in this scope

  A a = (A()+2);//problem with a temporary object

  return 0;
}

the cygwin output:

$ ./a.exe
d'ctor //this is from b or c
d'ctor //this is from b or c
d'ctor //this is from temporary
d'ctor //this is from a
Aborted (core dumped)

The delete operation has been executed twice on the same pointer, because it was shared between the temporary object and a.


This doesn't really answer your question (I'm not sure where the temporary variable is created myself), but in general, creating temporary primitive variables will not save any speed, because the only difference is the stack space used -- so whether the stack pointer is incremented by 4 bytes or 8 bytes is irrelevant to the speed of your program, unless there's a page fault (which is very unlikely). So you're unlikely to see any performance benefits with anything like this, especially if the compiler optimizes your code by putting variables in registers.


a*b creates a new temporary. Whatever the hell the rest of your question text means, I have no idea, but in as far as you use the word "temporary", one is created.

Given the code you claim the compiler is complaining about...the compiler should not be complaining. Since you've not included the real error...I have absolutely no clue why you think it's complaining about what you claim its complaining about.

Edit:

Given that you claim the code in your edit is the REAL code causing the error you also finally quoted, my bet is that the compiler has been completely confused by the line BEFORE the one it's complaining about:

const complex <double> I = (0.0,I);

I don't know what you indend for that to do, but it don't look legal to me.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号