Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a valid case for creating a temporary that is immediately destroyed and is not used directly in C++?

Inspired by this question. Suppose I have class Lock with a default constructor and in some code I write the following statement:

Lock();

this will have the effect of creating a temporary object of class Lock and immediately destroying it. Of course, creation could have some side effects and that would alter the program behavior, however that looks rather weird.

So my first guess is that such statements while completely valid from the language perspective are highly likely to contain a logical error.

Are there some valid usecases of the above statement? Are there some well-known and popular idioms that include such statements? Why would I want such statements in a correct program?

like image 220
sharptooth Avatar asked Jun 29 '11 09:06

sharptooth


3 Answers

It doesn't look any weirder than a call to a void function named Lock.

Not that I'm suggesting that you go around thinking of functions as just funny-named constructors (of whatever their return type is), but the syntax is intentionally similar.

I can't for the moment think of a good reason to create but not use a Lock, but:

LockSession(lock);

has the same side-effects as you'd expect from:

acquire_and_then_immediately_release(lock);

As you say, this is very rarely what you want, so it might well look to the casual reader like an error. If for some odd reason it is what you want, and you want to avoid confusing people, you can do:

{
    LockSession session(lock);
    // release immediately
}

or for that matter:

void acquire_and_then_immediately_release(Lock &lock) {
    LockSession(lock);
}

with the same effect and less chance of head-scratching whether that's really what you meant, or whether you've just made the common mistake of forgetting to supply a name and hence holding the lock for less time than you should.

Why would you want to acquire and then immediately release a lock? Probably because you're (ab)using it as a slightly peculiar semaphore. For example you could create a bunch of threads with a lock held, and if the first thing each thread does is this, then none of them will get past it until all the thread creation is done (plus anything else the parent wants the threads to be able to see) and the parent releases the lock. There are probably better examples out there of objects whose construction side-effects are significant.

Moving away from side-effects, another possibility is that if you want to check that a string is valid XML, you could write:

xml::dom::Document(mystring);

expecting an exception for invalid data. Again, the code would be more readable if you called a well-named function that does it. And constructing a DOM tree is not the most efficient way to validate XML. But if a class is what you already have then using it is the simplest thing that works.

I suppose the issue is that the name of a class is rarely descriptive of the side-effects of creating and destroying it. So a lone temporary will tend to look weird for that reason.

like image 53
Steve Jessop Avatar answered Sep 20 '22 14:09

Steve Jessop


In order to get away from dangerous va_list style variadics, I've written code that you call like this:

MyFunc() << a << b << c;

Where MyFunc is implemented as a class with an operator << and ~MyFunc() is responsible for doing the desired work. It's awkward to write the MyFunc class, but once it's done, it works well.

So, yes, the pattern of instantiating a temporary object that only lasts for one line can be useful.

like image 41
StilesCrisis Avatar answered Sep 19 '22 14:09

StilesCrisis


Similar syntax of creating a temporary is used many a times in template metaprograms or boost kind of libraries. They actually don't create temporary, but simulate its effect.

e.g. is_base_of

You can see temporary object syntax in the sizeof() trick.

like image 34
iammilind Avatar answered Sep 18 '22 14:09

iammilind