Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Tricky question

41 views
Skip to first unread message

Bonita Montero

unread,
Mar 28, 2021, 2:47:03 AM3/28/21
to
Is there a way to enforce that an object
can be only instantiated as a temporary ?

Alf P. Steinbach

unread,
Mar 28, 2021, 7:58:12 AM3/28/21
to
On 28.03.2021 08:46, Bonita Montero wrote:
> Is there a way to enforce that an object
> can be only instantiated as a temporary ?

No, because you can always bind it to a reference.

When an object such as an operator[] proxy result shouldn't outlive the
object that it refers to one could in principle guarantee that by having
all the objects dynamically allocated and using shared_ptr. But that
impacts negatively on efficiency, clarity, debuggability etc. plus
yields more awkward usage notation. One could then much better switch to
Java, C# or Rust.

So just add a stern comment in the relevant place.

- Alf

Bonita Montero

unread,
Mar 28, 2021, 3:05:32 PM3/28/21
to
> No, because you can always bind it to a reference.

I could assume that no one would be so stupid to do sth. like this:
Obj const &o = Obj();
So if I make this assumption, what's the solution ?

Juha Nieminen

unread,
Mar 29, 2021, 2:27:11 AM3/29/21
to
The lifetime of the temporary will be extended to the lifetime of the
reference in that case, so it's not completely stupid.

Juha Nieminen

unread,
Mar 29, 2021, 2:28:11 AM3/29/21
to
Bonita Montero <Bonita....@gmail.com> wrote:
> Is there a way to enforce that an object
> can be only instantiated as a temporary ?

I'm thinking what happens if all the member functions are
rvalue-qualified, but I haven't tested if that will introduce
that limitation. Maybe not.

Bonita Montero

unread,
Mar 29, 2021, 3:00:19 AM3/29/21
to
>>> No, because you can always bind it to a reference.

>> I could assume that no one would be so stupid to do sth. like this:
>> Obj const &o = Obj();
>> So if I make this assumption, what's the solution ?

> The lifetime of the temporary will be extended to the lifetime of the
> reference in that case, so it's not completely stupid.

You're right, and look at this:

#include <iostream>

using namespace std;

struct S
{
S()
{
cout << "S::S()" << endl;
}
~S()
{
cout << "~S::S()" << endl;
}
};

int main( int argc, char **argv )
{
S const &s = argc < 0 ? S() : S();
cout << "after destruction?" << endl;
}

Of course argc can never be < 0, but the compiler doesn't know that.
So look at the output:

S::S()
~S::S()
after destruction!
~S::S()

So the code destructs only one object within the statement !

Richard Damon

unread,
Mar 29, 2021, 7:46:02 AM3/29/21
to
You didn't define a copy constructor, so there may have been a second S
created as a copy of the first, to bind to the reference.


Bonita Montero

unread,
Mar 29, 2021, 12:56:41 PM3/29/21
to
>> You're right, and look at this:
>> #include <iostream>
>> using namespace std;
>>
>> struct S
>> {
>>     S()
>>     {
>>         cout << "S::S()" << endl;
>>     }
>>     ~S()
>>     {
>>         cout << "~S::S()" << endl;
>>     }
>> };
>> int main( int argc, char **argv )
>> {
>>     S const &s = argc < 0 ? S() : S();
>>     cout << "after destruction?" << endl;
>> }
>>
>> Of course argc can never be < 0, but the compiler doesn't know that.
>> So look at the output:
>> S::S()
>> ~S::S()
>> after destruction!
>> ~S::S()
>>
>> So the code destructs only one object within the statement !

> You didn't define a copy constructor, so there may have been a second S
> created as a copy of the first, to bind to the reference.

You have too much phantasy. That's for sure not required by the
standard, nor it would be realistic that any compiler would do
it that way.

Manfred

unread,
Mar 29, 2021, 1:59:21 PM3/29/21
to
It's no fantasy, that is what is happening in reality - if you use msvc
(gcc makes no copy) - you would have seen it yourself if you had a copy
(and a move) ctor defined.
[BTW ~S::S() should be S::~S()]

Paavo Helde

unread,
Mar 29, 2021, 3:27:00 PM3/29/21
to
If you think a copy ctor does not get used in your little experiment,
then how do you explain the output you saw? Or do you suggest the
compiler is buggy and destructs the same object twice? (Hint: it does not.)





Richard Damon

unread,
Mar 29, 2021, 9:51:41 PM3/29/21
to
Another good thing to do when generating this sort of trace is include
the 'this' pointer (i.e. the object address) and you would see that the
two destruction are at different addresses.

0 new messages