Scope of an inside-parenthesis declared object - c++

If I declare an object like this:
void main()
{
myclass objectA(anotherclass(true,true,0));
}
i.e. I create an objectA and another object "anotherclass" by directly calling the latter's constructor, what is "anotherclass"'s scope?
Does it get destructed only when main() finishes?

The temporary gets destructed at the end of the full expression that contains it, i.e. when the call to the constructor of myclass returns.
Per Paragraph 12.2/3 of the C++11 Standard:
Temporary objects are destroyed as the last step
in evaluating the full-expression (1.9) that (lexically) contains the point where they were created. This is true
even if that evaluation ends in throwing an exception. The value computations and side effects of destroying
a temporary object are associated only with the full-expression, not with any specific subexpression.
For this reason, if myclass's constructor takes an argument of type anotherClass by reference (either lvalue reference to const or rvalue reference), it shall not store it for future use, because it will be dangling if a temporary is passed, and dereferencing it would be Undefined Behavior.
It is only objectA that goes out of scope and gets destroyed when returning from the main() function.

The anotherclass object doesn't have a scope. Scope is a property of names, not of objects, and this object is not named. It's just a temporary object and will be destroyed at the end of the full expression.
Here's the definition of scope (§3.3.1):
In general, each particular name is valid only within some possibly discontiguous
portion of program text called its scope.

Related

const reference to member of temporary object [duplicate]

This question already has answers here:
About binding a const reference to a sub-object of a temporary
(3 answers)
Closed 6 years ago.
It is known feature of C++ that a const reference extends the life time of the temporary object returned from a function, but is it acceptable to use constant reference to the member of the temporary object returned from the function?
Example:
#include <string>
std::pair<std::string, int> getPair(int n)
{
return {std::to_string(n), n};
}
int main(int, char*[])
{
const int x = 123456;
const auto& str = getPair(x).first;
printf("%d = %s\n", x, str.c_str());
return 0;
}
Output:
123456 = 123456
Yes, this code is perfectly acceptable. The rules, according to the standard are ([class.temporary]):
There are two contexts in which temporaries are destroyed at a
different point than the end of the fullexpression. The first context
is when a default constructor is called to initialize an element of an
array. If the constructor has one or more default arguments, the
destruction of every temporary created in a default argument is
sequenced before the construction of the next array element, if any.
The second context is when a reference is bound to a temporary. The
temporary to which the reference is bound or the temporary that is the
complete object of a subobject to which the reference is bound
persists for the lifetime of the reference...
As you can see the highlighted line makes it clear that binding reference to sub-objects is acceptable, as the complete object has to have its lifetime extended as well.
Note that first does qualify as a subobject [intro.object]:
Objects can contain other objects, called subobjects. A subobject can
be a member subobject (9.2), a base class subobject (Clause 10), or an
array element. An object that is not a subobject of any other object
is called a complete object.
It's well defined.
From the standard: $12.2/6 Temporary objects [class.temporary]:
(emphasis mine)
The temporary to which the reference is bound or the temporary that is
the complete object of a subobject to which the reference is bound
persists for the lifetime of the reference
And about the subobect, $1.8/2 The C++ object model [intro.object]:
(emphasis mine)
Objects can contain other objects, called subobjects. A subobject can
be a member subobject ([class.mem]), a base class subobject (Clause
[class.derived]), or an array element. An object that is not a subobject of any other object is called a complete object.
first is bound to reference and it's the member subobject of std::pair, so the temporary std::pair (i.e. the complete object) 's lifetime will be prolonged, the code should be fine.
For reference only: Clang and GCC say yes, VC says no.
As I mentioned in my comment:
The lifetime of the temporary should be prolonged as long as the
lifetime of its member access (str in this case). That said, you
should be just ok by taking return value by copy. RVO will avoid doing
extra copies.
From the standard, section 12.2.5:
The second context is when a reference is bound to a temporary. The
temporary to which the reference is bound or the temporary that is the
complete object of a subobject to which the reference is bound
persists for the lifetime of the reference except:
— A temporary bound to a reference member in a constructor’s
ctor-initializer (12.6.2) persists until the constructor exits.
— A temporary bound to a reference parameter in a function call
(5.2.2) persists until the completion of the full-expression
containing the call.
To stay clear out of any trouble, I would rather do:
auto m_p = getPair(x);
This is as efficient as it can get because of RVO which every compiler must be doing for this case.
This seems addressed in 12.2/4-5:
There are two contexts in which temporaries are destroyed at a
different point than the end of the full expression. The first
context... [stuff dealing with arrays]
The second context is when a reference is bound to a temporary. The
temporary to which the reference is bound or the temporary that is the
complete object of a subobject to which the reference is bound
persists for the lifetime of the reference except:
There are four exceptions dealing with constructor binding of reference members, function calls, functions returning by reference, and references bound in new-initializers.
None of these cases apply, so the temporary is destroyed at the end of the full statement, leaving a dangling reference to a member of the temporary.
Just help the compiler realize it can move from the temporary: const auto str = std::move(getPair(x).first);

Some questions on life span of a string object

Trying to understand c++ string a little more here. Compiler here is g++ 4.7.3.
Question 1: In the following code snippet, will the compiler be smart enough to free the user data (in the heap, implicitly pointed to by s) at the end of the function? I think the answer is yes, just want to confirm.
void dummy() {
string s;
s.append("hello");
//more append
}
Question 2: in the following snippet, compiler will not free the user data pointed to by s when the function returns. Is that right? If so, the user data may be freed in the caller by the compiler (if the caller function itself doesn't return the string object).
string dummy() {
string s;
s.append("hello");
//more append
return s;
}
//some caller
string s1 = dummy();
In question 1, yes the memory for the variable s will be freed when the function dummy ends because that was the enclosing scope of the s variable.
In question 2, the compiler will likely use return value optimization to avoid having to copy the memory from s into s1, since s is about to fall out of scope.
Question 1: In the following code snippet, will the compiler be smart enough to free the user data (in the heap, implicitly pointed to by s) at the end of the function?
Yes, it is required to. At the end of the function scope, the string's destructor will be called, which will free the memory allocated.
The object s is said to have "automatic storage duration", and it's described by the standard via §3.7.3/1:
Block-scope variables explicitly declared register or not explicitly declared static or extern have au- tomatic storage duration. The storage for these entities lasts until the block in which they are created exits.
Question 2: in the following snippet, compiler will not free the user data pointed to by s when the function returns. Is that right? If so, the user data may be freed in the caller by the compiler (if the caller function itself doesn't return the string object).
The compiler may elide the copy there, using what's called RVO (return value optimization). Specifically the standard words this in the following way, in §12.8/31:
This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):
in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv- unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value
in a throw-expression (5.17), when the operand is the name of a non-volatile automatic object (other than a function or catch-clause parameter) whose scope does not extend beyond the end of the innermost enclosing try-block (if there is one), the copy/move operation from the operand to the exception object (15.1) can be omitted by constructing the automatic object directly into the exception object
when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move
when the exception-declaration of an exception handler (Clause 15) declares an object of the same type (except for cv-qualification) as the exception object (15.1), the copy operation can be omitted by treating the exception-declaration as an alias for the exception object if the meaning of the program will be unchanged except for the execution of constructors and destructors for the object declared by the exception-declaration. [ Note: There cannot be a move from the exception object because it is always an lvalue. —endnote]

C++: when object constructed in argument is destructed?

When object constructed in argument is destructed, before of after function call?
E.g. is the following code safe?
void f(const char*)
{ ... }
std::string g()
{ ... }
...
f(g().c_str());
It always works for me but I don't know is it just undefined behaviour or it actually should work.
g() is a temporary. Lifetime of tempraries extends for the entire time of evaluation of the entire full-expression (in your case, that would be f(g().c_str())) Therefore your usage is safe, unless the f() stores the pointer somewhere.
§12.2/4 There are two contexts in which temporaries are destroyed at a different point than the end of the fullexpression. The first context is when an expression appears as an initializer for a declarator defining an object. In that context, the temporary that holds the result of the expression shall persist until the object’s initialization is complete. [...]
§12.2/5 The second context is when a reference is bound to a temporary. [...]
Neither of these two cases apply in your example.
A temporary object constructed as part of an expression evaluation is destructed after evaluating the full expression containing the expression, unless it is bound to a named reference. (12.2 and 1.9 in the current draft standard are the relevant sections).
So in your example, the temporary constructed to hold the return value of g will be destroyed after f returns.
It always works for me but I don't know is it just undefined behaviour
or it actually should work.
No, there is no undefined behavior because temporary object produced by g() will be deleted after evaluating full expression, that is body of f() function.
C++ Standard n3337 § 12.3/3
When an implementation introduces a temporary object of a class that has a non-trivial constructor (12.1,
12.8), it shall ensure that a constructor is called for the temporary object. Similarly, the destructor shall be
called for a temporary with a non-trivial destructor (12.4). Temporary objects are destroyed as the last step
in evaluating the full-expression (1.9) that (lexically) contains the point where they were created. This is true
even if that evaluation ends in throwing an exception. The value computations and side effects of destroying
C++ Standard n3337 § 12.3/4
There are two contexts in which temporaries are destroyed at a different point than the end of the full-
expression. The first context is when a default constructor is called to initialize an element of an array. If
the constructor has one or more default arguments, the destruction of every temporary created in a default
argument is sequenced before the construction of the next array element, if any.
C++ Standard n3337 § 12.3/5
The second context is when a reference is bound to a temporary. (...)

Will the lifetime of a temporary created in the argument list to a function taking a *non*-const reference parameter encompass the function call?

I have become accustomed to the fact that a const reference extends the lifetime of a temporary until the reference goes out of scope:
class X {};
{
X const & x = X();
// Lifetime of x extended to the end of the scope
// in which x is declared because it was declared
// as a *const* reference
}
... And I am also aware that a temporary lives until the end of the expression in which it is created:
// Contrived example to make a point about lifetime of a temporary in an expression
class Y
{
public:
Y() : y(5) {}
Y & operator+=(int const & rhs)
{
y += rhs;
return *this;
}
int foo() { return y; }
private:
int y;
};
// n in the following line of code is 11 and the code is valid
// - the lifetime of the temporary persists to the end of the expression
int n = (Y() += 6).foo();
Assuming I am correct about both of the above, I suspect that it is true that a temporary created in a function argument list will persist for the lifetime of the function call even if it is bound to a non-const reference:
class X {};
void foo(X & x)
{
// x is valid in this function,
// even though the parameter is declared
// as a *non*-const reference - correct?
}
// Valid, I think, even though the function parameter
// is declared as a **non**-const reference
// - because the lifetime of the temporary persists until the expression
// is fully evaluated - right?
foo(X());
I imagine that my experience and understanding is correct - that it is safe to bind the temporary created in the function argument list to the non-const reference parameter.
But I'd like to confirm I am right about this, because I was not able to find this question explicity answered anywhere.
Thanks!
Sure you are right.
The standard:
12.2 Temporary objects [class.temporary]
[...]
There are two contexts in which temporaries are destroyed at a different point than the end of the fullexpression.
The first context is when a default constructor is called to initialize an element of an array. If
the constructor has one or more default arguments, the destruction of every temporary created in a default
argument is sequenced before the construction of the next array element, if any.
The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except:
— A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits.
— A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion of the full-expression containing the call.
— The lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is not extended; the temporary is destroyed at the end of the full-expression in the return statement.
— A temporary bound to a reference in a new-initializer (5.3.4) persists until the completion of the
full-expression containing the new-initializer.
Want to ask the question again using one more level of constructors, and objects storing references?
Deduplicator has given the language lawyer answer, here is the implementation detail answer:
If you pass any object by reference, you are effectively passing a pointer to that object. Since the caller is only passing a pointer to the object, the object that is passed by reference must be constructed by the caller.
The callee, on the other hand, only ever sees the pointer that is passed in. It does not see how the caller has constructed the object whose pointer is passed. This object could be a temporary (only in the case of a const reference, because temporaries cannot be passed as non-const references), or a variable with function scope, it could be an object that was already passed to the caller by its caller, it could even be an object allocated with new. As such, it cannot destruct the object because it does not know how.
Consequently, it is up to the caller to clean up the temporary after the callee returns control to the caller - anything that is passed in by reference must live for the entire runtime of the callee.
Note that this entire argument is completely ignorant as to whether the reference is const or not.

what happens when i only call a constructor?

This may sound naive. I want to know what happens when i explicitly call a constructor like this:
class A{
/*...*/
public:
A(){}
};
int main(){
A();
return 0;
}
Is a useless object created which remains in the memory until the scope of main() ends?
You create an object that lasts until the end of the statement.
Its considered a nameless temporary which gets destroyed after the end of the full expression. In this case, the point right after the semicolon. To prove this, create a destructor with a print statement.
when i explicitly call a constructor like this
You are not calling a constructor here; but creating a temporary object which gets destructed immediately. Constructor can be called explicitly with an object of that type (which is not advisable).
Is a useless object created which remains in the memory until the
scope of main() ends?
It doesn't have scope till the function ends, but till the ; ends.
Strictly speaking you can never make a direct call to a constructor in C++. A constructor is called by the implementation when you cause an object of class type to be instantiated.
The statement A(); is an expression statement and the expression is a degenerate form of an explicit type conversion (functional notation). A refers to the type, strictly speaking constructors don't have names.
From the standard (5.2.3 [expr.type.conv] / 2:
The expression T(), where T is a simple-type-specifier for a non-array complete object type or the (possibly cv-qualified) void type, creates an rvalue of the specified type, which is value-initialized [...].
Because your class type has a user-declared default constructor the value-initialization of this temporary will use this constructor. (see 8.5 [dcl.init]/5)
Okay, I re-visited temporary and found that in the above example, it's actually a part of expression that is initializing an object. So yes, the scope ends at ;
Here:
When a temporary object is created to initialize a reference variable, the name of the temporary object has the same scope as that of the reference variable. When a temporary object is created during the evaluation of a full-expression (an expression that is not a subexpression of another expression), it is destroyed as the last step in its evaluation that lexically contains the point where it was created.