Scope for temporary variables?

Hello,
I was wondering if I could get some opinions on something, or if someone knows a better way to do this to let me know. I need to make a matrix by multiplying a column vector by a row vector. After this multiplication, I do not need the two vectors anymore and want them to go away. The best solution I could think of was to put this inside a temporary scope so that the vectors are destroyed when it end. What I mean is
1
2
3
4
5
6
7
    Matrix<double, Dynamic, Dynamic> F;  //Dynamic size matrix
    {//use this section to make temporary vectors Vec1 and Vec2 to fill he Matrix F

        Matrix<double, 1, Dynamic> Vec1;  //Dynamic size row vector
        Matrix<double, Dynamic, 1> Vec2;  //Dynamic size column vector
        F = Vec2*Vec1;
    }


Where Vec1 and Vec2 no longer exist after this but F survives. Does anyone know if this is "bad c++" or if there is a better way to do it? thanks!
Last edited on
I find this rather strange, you don't seem to actually seem to assign any values to Vec1 or Vec2 - I would've thought that your default constructor initializes your Matrices to 0, so your F would always be a 1x1 0 matrix?

Otherwise, there isn't anything particularily "wrong" with this, but if your functions are so big that you need to keep names out of the local namespace, maybe you should think about refactoring.
Personally I think a function would be more appropriate than an anonymous block sitting in the middle of the code.
1
2
3
4
5
6
Matrix<double, Dynamic, Dynamic> func()
{
        Matrix<double, 1, Dynamic> Vec1;  //Dynamic size row vector
        Matrix<double, Dynamic, 1> Vec2;  //Dynamic size column vector
        return Vec2*Vec1;
} 


The main advantage being that you can keep your main block of code fairly lean (smaller functions which have fewer nested blocks are generally much nicer to read IMO):
Matrix<double, Dynamic, Dynamic) F = func();

Better still, if you're on a newer compiler which supports the C++11 "auto" feature:
auto F = func();

As an added bonus, initialising your Matrix using the return from a function might potentially be more efficient - particularly if your Matrix<> class has implemented C++11 move semantics.
Hi
@Bench82

When you use a function to do the multiplication and return a new object, your code may look better and you may use the function at many places, however this has a penalty , creating and destroying temporary objects.


Last edited on
Hey,
Thanks for the replies. hanst99, you are correct that I didn't assign it any values so I would just have a 0 matrix. I guess I should have done something to give it values, but I was just trying to illustrate what I wanted to do in as short code as possible. I felt that putting a random block in the middle of my code would be kinda weird. I think Ill just make a function to do it more cleanly. thanks!
@therockon7throw
There's no penalty; it can actually be more efficient to do that (even with an older C++98/03 compiler) because temporary objects are nearly always optimised out when you initialise an object from a function return.

For example, using a class which has no move semantics (i.e. legal C++98/03 code)
1
2
3
4
5
6
7
8
9
10
11
12
13
struct foo
{
    foo()           { std::cout << "Ctor"   << std::endl; }
    foo(const foo&) { std::cout << "CCtor"  << std::endl; }
    ~foo()          { std::cout << "Dtor"   << std::endl; }

    foo operator* (const foo&)
    {
        foo bar;
        std::cout << "multiplication" << std::endl;
        return bar;
    }
}; 


Using method 1 as per the OP:
1
2
3
4
5
6
7
8
9
int main()
{
    foo bar1;
    {
        foo bar2;
        foo bar3;
        bar1 = bar2 * bar3;
    } 
} 

Output: (no function initialisation)

1
2
3
4
5
6
7
8
9
10
11
Ctor
Ctor
Ctor
Ctor
multiplication
CCtor
Dtor
Dtor
Dtor
Dtor
Dtor 
Note that there are 5 objects created in total, including temporaries.


However, using a function call, one of those objects is optimised out automatically by the MS Visual C++ compiler:
1
2
3
4
5
6
7
8
9
10
11
foo create_foo()
{
    foo bar2;
    foo bar3;
    return bar2 * bar3;
}

int main()
{
    foo bar1 = create_foo();
} 


Output: (Function initialisation)
1
2
3
4
5
6
7
8
9
Ctor
Ctor
Ctor
multiplication
CCtor
Dtor
Dtor
Dtor
Dtor 
So, far from being a penalty, there's actually a benefit. (Which of course is compiler-dependent), however even on compilers which don't make this optimisation it should never be less efficient to do it this way


However, as I alluded to in my original post, optimisations alone aren't usually a good reason for doing something, but readability certainly is; the efficiency gained is more of a bonus.

Last edited on
You can do it by using unnamed temporary objects. That is, instead of

1
2
3
4
5
6
7
    Matrix<double, Dynamic, Dynamic> F;  //Dynamic size matrix
    {//use this section to make temporary vectors Vec1 and Vec2 to fill he Matrix F

        Matrix<double, 1, Dynamic> Vec1;  //Dynamic size row vector
        Matrix<double, Dynamic, 1> Vec2;  //Dynamic size column vector
        F = Vec2*Vec1;
    }


you can write

1
2
    Matrix<double, Dynamic, Dynamic> F;  //Dynamic size matrix
    F = Matrix<double, Dynamic, 1>() * Matrix<double, 1, Dynamic>();
Last edited on
Topic archived. No new replies allowed.