C ++

Source: Internet
Author: User

1. It is best not to use the reference Return Value

Some users use the reference method when passing parameters to avoid the creation of temporary objects and improve the efficiency. Can they use references when returning values?

See the following code:

Copy codeThe Code is as follows: class Rational {
Public:
Raional (int numerator = 0, int denominator = 1 );
...
Private:
Int d, d;
Friend Rational operator * (const Rational & lhs, const Raional & rhs );
};
Rational: operator * (const Rational & lhs, const Raionl & rhs)
{
Return Rational result (lhs. n * rhs. n, lhs. d * rhs. d );
}
}

This class is the rational number class we introduced earlier. Here I think there will be a class structure and class destructor. Can this problem be avoided if reference is used? Can it improve efficiency?

There are two ways to create a new object for a function. One is to create an object in the stack (statck), and the other is to create an object in the heep (heep.

Copy codeCode: People p (a, B) // create a stack
People * p = new People (a, B) // create in heap

Now we should first create a variable in the stack, but the created variable is a local variable and will be destroyed before exiting the function.Copy codeThe Code is as follows: const Rational & operator * (const Rational & lhs, const Rational & rhs)
{
Rational result (lhs. n * rhs. n, lhs. d * rhs. d );
Return result;
}

In a function, the Space Creation object in the stack mode is a local object. If any function returns a reference pointing to a local object, an error will occur. Because the local object is destroyed before the function exits, it means that the object referred to by reference does not exist.
So we want to createCopy codeThe Code is as follows: const Rational & operator * (const Rational & lhs, const Rational & rhs)
{
Rational * result = new Rational (lhs. n * rhs. n, lhs. d * rhs. d );
Return * result;
}

Now another problem is found. Who will delete the new object? Okay. Check the following when taking the lead.Copy codeThe Code is as follows: Rational w, x, y, z;
W = x * y * z;

Here, a statement calls operator * twice at the same time, which means that the new statement needs to be deleted twice. However, there is no reasonable way for the opertaor * user to perform those delete calls, because the user cannot obtain the returned pointer, which causes resource leakage.
Therefore, a reference is returned, pointing to the static Rational object defined in the function.Copy codeThe Code is as follows: const Rational & operator * (const Rational & lhs, const Rational & rhs)
{
Static Rational result;
Result = ...;
Return result;
}

It is obvious that it is multithreading. Is it safe to write in a multi-threaded environment? If multithreading is not involved. So what will happen to the following code?Copy codeThe Code is as follows: bool operator = (const Rational & lhs, const Rational & rhs );
...
Raional a, B, c, d;
If (a * B) = (c * d)
{
...
}

The above if statement expressions are true regardless of a, B, c, and d, because they all point to the same static value.

2. It is best not to place all variable definitions at the beginning of a statement.

Some people may have taken C language courses, who like to learn C and put all the variable definitions at the beginning. But in C ++, I suggest you do not do this, because when defining a variable, the program is doomed to require a construction and analysis. For example, in the following procedure: we allow students under 1 meter and 8 years old to buy a ticket.

Copy codeThe Code is as follows: class People {...};
Class Ticket {...};
Bool Isvalid (const People & p ){...}
Void Banding (const People & p, Ticket & t );
Ticket buyTicket (const People & p)
{
Ticket t;
If (Isvalid (p) {return NULL };
// Bind the information to the ticket
Banding (p, & t );
Return t;
}

If the conditions of the ticket owner are not met, you cannot enter the ticket to bind the ticket, here, the Ticket t statement makes the function bear the construction cost and analysis cost of a Ticket.
Therefore, it is best not to define variables in advance. It is best to define variables when necessary to avoid unnecessary performance overhead. The above example is changed to the following:

Copy codeThe Code is as follows: class People {...};
Class Ticket {...};
Bool Isvalid (const People & p ){...}
Void Banding (const People & p, Ticket & t );
Ticket buyTicket (const People & p)
{
If (Isvalid (p) {return NULL };
Ticket t;
// Bind the information to the ticket
Banding (p, & t );
Return t;
}

3. It is best not to convert too many types.

One of the design goals of C ++ rules is to ensure that "type errors" are impossible. Theoretically, a program is compiled to indicate that it does not attempt to perform any insecure or absurd operations on any body. It is a pity that the type conversion breaks through the type system, which may cause any type of trouble, which may be very troublesome. For example, the last code example in this article. Both C and C ++ support implicit type conversion, and C ++ has four types of display conversion operators. This section describes how to choose between a member function and a non-member function. However, it is recommended that you do not perform too many type conversions to avoid them. Type conversion is often not based on what you mean. First, let's look at an example:

Copy codeThe Code is as follows: # include <iostream>
Class base
{
Public:
Base (): a (0), B (0 ){}
Base (const int & x, const int & y)
: A (x), B (y ){}
Virtual void init ()
{
A = 5;
B = 5;
Std: cout <"in base a value is" <a <std: endl;
Std: cout <"in base B value is" <B <std: endl;
}

Int get_a () const
{
Return;
}

Int get_ B () const
{
Return B;
}
Private:
Int;
Int B;
};

Class derived: public base
{
Public:
Derived (int x, int y): base (x, y ){}
Void init ()
{
Static_cast <base> (* this). init ();
}
};

The running result is
In base a value is 5
In base B value is 5
A value is 2
B value is 2

Here, the derived type is converted to base, but calling the base: init () function is not a function on the current object, this is a copy of the base of the object created by the previous transformation action. So when we try to change the object content, we actually change the copy content, and the object content is not changed.

How can this problem be solved? We can directly declare the function that calls the base class.

Copy codeThe Code is as follows: class derived: public base
{
Public:
Derived (int x, int y): base (x, y ){}
Void init ()
{
// Static_cast <base> (* this). init ();
Base: init ();
}
};

The running result is:
In base a value is 5
In base B value is 5
A value is 5
B value is 5

Perhaps you should remember to use dynamic_case (if you have read the previous article: it is used to safely perform type conversion down the inheritance relationship ). An error occurs directly when dynamic_cast is used.

Copy codeThe Code is as follows: class derived: public base
{
Public:
Derived (int x, int y): base (x, y ){}
Void init ()
{
// Static_cast <base> (* this). init ();
// Base: init ();
Dynamic_cast <base *> (this)-> init ();
}
};

The running result is:

Segment error (Master memory) Information dump) Assume that a class has a five-layer single-inheritance relationship. If dynaic_cast is executed on this object, there will be up to five strcmp calls, the higher the depth or multi-inheritance, the higher the cost. Dynamic_cast is required because it wants to execute the derived class operation function on the derived class object, but currently there is only one pointer or reference pointing to the base, which can be used for processing at this time.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.