Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are the following 3 ways to define objects identical?

In my understanding the following are identical:

Person p{}; // Case 1
Person p = {}; // Case 1.5

I noticed

Person p = Person{}; // Case 2

produces the same tracing output as the Case 1 and Case 1.5 above.

  • Question 1: Comparing case 2 with either case 1 or case 1.5, is it because of copy elision or something else?

  • Question 2: What are the differences between the following?

Person p{};            // Case 1
Person p = Person{};   // Case 2
Person&& p = Person{}; // Case 3
like image 873
xport Avatar asked Sep 27 '20 17:09

xport


People also ask

How do you define an object?

An object is a collection of properties, and a property is an association between a name (or key) and a value. A property's value can be a function, in which case the property is known as a method. In addition to objects that are predefined in the browser, you can define your own objects.

How can you tell if an object is the same?

To determine if two objects are not identical Set up a Boolean expression to test the two objects. In your testing expression, use the IsNot operator with the two objects as operands. IsNot returns True if the objects do not point to the same class instance.

Which of the following is the correct way of defining objects in JavaScript?

Using an Object Literal This is the easiest way to create a JavaScript Object. Using an object literal, you both define and create an object in one statement. An object literal is a list of name:value pairs (like age:50) inside curly braces {}.

How many ways can you declare an object in JavaScript?

You can create an object in three different ways: Using object literal. By creating instance of Object directly. By using constructor function.


1 Answers

The three statements are not entirely identical in c++11.

Case 2 requires move construction prior to C++17

The language requires that a move-constructor exist for code of X x = X{} -- otherwise the code will fail to compile.

For example, using a Person class defined like:

class Person{
public:
    ...
    Person(Person&&) = delete;
    ...
};

will fail to compile on statements like:

Person p = Person{}; // Case 2

Example on compiler explorer

Note: that the above code is completely valid in c++17 and onward due to wording changes that allow for objects to be constructed directly in their destination address even when immovable and uncopyable (this is what people often refer to as "guaranteed copy elision").

Case 3 is a lifetime extension of a temporary

The third case is a construction of a temporary whose lifetime is extended by being bound to an rvalue-reference. Lifetime of temporaries can be extended under certain cases where they are bound to either rvalue references or const lvalue references. For example, the following two constructions are equivalent in that they bind to a temporary's lifetime:

Person&& p3_1 = Person{};
const Person& p3_2 = Person{};

As far as scoping rules go, this has the same lifetime as any other automatic variable (e.g. it will invoke a destructor at the end of the scope in just the same way as Person person{} will). However what can be done with construction, at least in c++11, is quite different from Person p2 = Person{} in that this code will always compile even if a move constructor is not present (since this is a reference binding).

For example, lets consider an immovable, uncopyable type like std::mutex. In C++17 it's valid to write code of:

std::mutex mutex = std::mutex{};

But in C++11 that fails to compile. However, you are free to write:

std::mutex&& mutex = std::mutex{};

Which creates and binds a temporary to a reference whose lifetime will be the same as any scoped variable constructed at that point.

Example on compiler explorer.

Note: Intentionally propagating lifetime of a temporary object is not commonly an intentional thing to do, but back before C++17 this is the only way to achieve an almost-always-auto syntax with immovable objects. For example, the above could be rewritten: auto&& mutex = std::mutex{}

like image 79
Human-Compiler Avatar answered Oct 20 '22 14:10

Human-Compiler