SolmyR's small text series: copy

zhaozj2021-02-17  166

"Zero help ~~"

"Splendid" smile, full of sincere eyes, plus the posture nodded, and these three constitute a statue named "asking for people".

Looking up at QQ, Zero looked up, watching the statue of the statue of the statue --- Pisces, the only female programmer in 50 meters in Fangyuan - ask: "What?"

"I have a C program here."

"You should ask SolmyR this kind of question."

"Oh, don't make a joke, I dare to ask him! I always say that I am stupid! I asked him a small problem last time, and the result of the dog blood sprinkler, hehe!", Pisces seemed, "or you come to help Let me know that you are a number of masters in the department, and I'm sure it. Help! ~~ "

ZERO is obviously impressed, so, under the effort of Pisces, Zero sat before the Pisces.

"Well, what is the problem?"

"This is this, there is a set of C-style APIs, responsible for managing the character communication link on the device. They are designed for some years," said, Pisces tested some code:

// Old C Style ApityPedef INT CONN_HANDE; TYPEDEF STRUCT {/ * ... Opens the parameters and attributes required for the link ... * /} conn_attr;

CONN_HANDLE OPEN_CONN (conn_attr * p_attr, char * buf, unsigned int buf_size); void close_conn (conn_handle h);

Char read_conn (conn_handle h); void write_conn (conn_handle h, char c);

...

"The branches are not counted, the trunk is probably, the one-on function is responsible for opening and closing, a pair of functions are responsible for reading and writing. The BUF parameter when creating a link pointing to a buffer, this is to assign and pass the length itself. Words and links, read_conn / write_conn will use it to make a buffer. My task is to write a class to put these API packages. ", Said Pisces called another code:

// Pisces' Connection ClassClass Connection {Private: Conn_attr M_ATTR; BOOL M_OPENED; int m_bufsize; char * m_buf;

CONN_HANDLE M_H; ...

PUBLIC: ConN_ATTR & Attr, INT BUFSIZE) {m_attr = attr; m_pened = false; m_bufsize = buffsize; m_buf = new char [m_bufsize];} ~ connection () {delete m_buf;}

Void open () {m_h = open_conn (& m_attr, m_buf, m_bufsize); m_pened = true;} void close () {close_conn (m_h); m_pened = false;}

Char read () {assert (m_opened); Return Read_conn (m_h);} void write (char c) {assert (m_opened); Write_Conn (M_H, C);} ...};

"It should be very simple, but I don't know what is going on. The program with the Connection class is always crashing from time to time, saying is an illegal memory operation.", Pisces is very distressed.

ZERO saw a problem with a look - this made his little self-sounding - but did not move on the surface, waited until he had seen the code segment provided by Pisces, he opened. Say:

"This is a common error Pisces", ZERO as much as possible to listen to an authority, "About C , there is an important guiding principle: the destructor, copy constructor, and assignment operator, almost always It is true together. That is, if you write a destructor for a class, then you have to provide a copy constructor and an assignment operator, which violates it. You see here: "

Said, Zero marked two lines of code on the screen:

Void Some_Func () {conn_attr attr; ... connection c1 (512, attr); connection tmp = c1; ...}

"Here the object TMP is constructed from the C1 copy, and you do not define a copy constructor, which allows the compiler to automatically select a copy of the bit, which makes all members of TMP and C1, including M_BUF members. Such When the function returned, DELETE was over again when the function returned, and DELETE was over again when TMP destructure ... "

"Oh! I understand!" Pisces interrupted Zero, "So there is an illegal memory operation, right? Oops, this time I have encountered the String class in the school, how can I forget? "

'

"I can, thank ZERO!"

Zero returned to his seat, starting to continue and "you don't understand my thin heart" to explore "the meaning of love" on QQ. However, the good is not long, not long, the scene described in this article once again appeared again.

"Zero help ~~"

Zero sighed in his heart and asked: "What is the problem, Pisces?"

"Oh, or that class. I added a copy constructor to CONN, I illegally stored, but still, there is a problem with link transmission data ---- You still come over to help me Take a look ~~ "

Zero is not willing to come to the Pisces's computer, turn out the copy constructor written by the Pisces:

connection (const connection & other) {m_attr = other.m_attr; m_bufsize = other.m_bufsize; m_buf = new char [m_bufsize]; memcpy (m_buf, other.m_buf, m_bufsize); m_opened = other.m_opened; m_h = other.m_h; }

Zero's brow wrinkled, this copy constructor seems to be able to solve the problem, apparent that two M_BUF now points to legitimate memory, no longer there is a problem of two releases. So where is the problem? Zero has fallen into meditation. But only more than 1 minute, Zero understood.

"Oh! I understand! I will see the ghost, how can I not pay attention to this .pisces, the problem is still on the m_buf, because the link and buffer pointer are one or one, so the newly allocated buffer in the copy constructor is not kick in."

Pisces blinked, and the expression was slightly lag.

"Give you an example." Zero flying into a test code:

Connection * pc = NULL;

{Conn_attr attr; Connection C1 (512, Attr); c1.open (); pc = new connection (c1);

PC-> Write ('a');

"C1 constructor calls new to allocate memory for its m_buf member, followed by calling open_conn in the Open function to open a link, note that the parameter we passed to Open_CONN is C1.M_BUF, so this link corresponds to buffer pointers Is C1.m_buf. Then we execute the PC = New Connection (C1), the new object is constructed from the C1 copy, so PC-> M_H and C1.m_h are equal, that is, the two objects saved M_H identifies the same link, The corresponding buffer pointer is C1.M_BUF ---- "

Zero was stopped like SolmyR, but it was disappointed to see Pisces without reacting. He had to say:

"So the next PC-> WRITE is called Write_Conn, this API doesn't know that this is called by another object, it still tries to use C1.M_BUF as a buffer, but this time C1 has ended its life. The cycle, C1.m_buf has been released, so this is an illegal memory access. "

Pisces licked the lips: "... that ... What should I do now?"

ZERO turned over white - it was obvious that Pisces did not understand what happened - starting to consider how to deal with the problem before you.

"Well, look like, here you must consider a plurality of objects to share a pointer problem, um, in order to ensure that this memory is released ... I am afraid ... I am afraid I have to use the counting technology (see" small piece series five: garbage collection ") I have been determined, do you want to use Boost :: Shared_Ptr?", Zero thought, side himself. suddenly ---

"The logic's confusion leads to complexity, ZERO, this Connection class thousands of holes." SolmyR's voice is unambiguous.

ZERO controls the impulse of unplugging legs in 0.01 seconds, so as soon as possible, the gesture is slowed down. In front of him is a consistent elegant SolmyR, a juice, a juice, and it is firmly struggling to tried to escape the Pisces. "Ah Solmyr, I am looking for you, this question is a bit tricky."

"Is it? Why is your legs?"

"Well? Nothing, it's a bit cold ... ah Solmyr, what did you just say?"

"Logic chaos leads to complex, Zero, this Connection class thousands of holes." SolmyR put Pisces on the seat next to them, and then said: "The problem you just discovered is only one of them. Look at this "

Void Some_Func () {conn_attr attr; ... Connection C1 (512, Attr); c1.open (); ... connection tmp = c1; c1.close (); tmp.write ('a'); .. }

"What will this cause?"

"... try to write a link that has been closed."

"I also need to give multiple openings multiple times, turn off a link multiple times, and various links are open, but will read and write examples of assertion errors?"

" …… no need."

"Then how do you plan to fix these problems? Do you want to save a list of objects that are constructed by it in each object? Or you intend to write 'below 371 methods in the document to use this class to cause unpredictable errors' ? "

"..."

Solmyr is sighing: "You are misleaded by Pisces, Zero, because you only think how to help Pisces to solve the problem, if you let you design this class at the beginning, the situation will not be so bad." Say, Solmyr Pleveted Pisces. "Don't forget, the C class is not simple to make a bunch of members variables and member functions, always remember this principle: C use class to express the concept."

Zero nodded.

"I will ask you, what should I say this class?"

"Hey, you should represent 'link' concept."

"A Connection class should be representative ..."

"Should represent an actual 'link'."

"It's very good. So you tell me what you just want to design the copy constructor?"

"... Let two connection objects can represent the same link."

"and so ……"

"... So ... um ... oh ..." Zero revealed the expression that suddenly realized: "So I actually want to do this: if a connection object is not copied, it represents a separate link If it is copied, then it will represent the same link with the copyman, which also includes copyers of the copyman, copyworship of the copyman's copyman ... God, this is a mess! "

"Yes, the problem is here. What is the Connection object? What is the answer to a logically very confusing answer, which leads to the complexity of the implementation. In fact, if this logic is cleared, the problem is very simple: A Connection object represents a link, it constructed, representing a link; it destructure, representing this link, finished its life history - here Open and Close These two member functions are excessive. As for copy construction ... ... "SolmyR suddenly talked, taking a catenished tone:

"Should be prohibited."

"Forbidden copy ?!"

"Yes, it should be prohibited. In fact, for the concept of 'link', 'copy' action meaning fuzzy: What does the copy mean? What is the link between the copy constructed and the original link? When using the Connection class The programmer saw the connection C2 = C1; when he could not see what this means from the code itself. He guess that C1 and C2 represent a link? Or two links? Can only access it? Documentation is solved, which increases the user's burden, and if copying, all intellectual programmers will understand a link that each Connection object represents a link. "

Zero nodded if he thought.

"At the same time, this can also prevent programmers from passing the Connection object to the function - imaginary, if a programmer uses connection, what happens?", SolmyR typed the following code:

Void Send_a_greeting (Connection C) {C.Write ("Hello!");

ZERO did not expect the problem: "The designer of the function thinks he is sending a message in the link to the caller, but in fact, this function creates a new link when the parameters are passed."

SolmyR nodded and continued: "Also, from the perspective of scalability, you should also prohibit copying. For example, suppose you intend to control the creation of the link, put the creation process, then this copy constructor is in you A big hole is smashed on the package --- Everyone can use copy constructs to create a link; At that time, the copy construct of Connection must be prohibited, and the price of your previous support to the copy structure is the hard to go through all the codes to remove all copy constructs. "

"That, if I really need to visit a link, it ..." Zero didn't wait for SolmyR to answer, I took it up, "Oh, it is very simple, as long as it passes the reference, or if you need better Control, you can use a smart pointer what. "

"It is completely correct. In fact, many classes - more than many people think more - the concept of the representation is not clear for the 'copy', such as common 'windows',' File ',' transaction ', etc., prohibiting them from copying to make the logic of the code clearly, after you design, you can first consider whether it is forbidden, if you can't stop it, let's consider how Write a copy of the constructor. Ok Zero, can you give the Connection implementation? "

"SURE! As long as the copy constructor and the overload assignment operator are set to private, you can disable copy." Zero dragged the keyboard, there was a new implementation on the screen: Class Connection {private: conn_attr m_attr ; Int m_bufsize; char * m_buf;

CONN_HANDLE M_H; ...

public: connection (const conn_attr & attr, int bufsize): m_attr (attr), m_bufsize (bufsize) {m_buf = new char [m_bufsize]; m_h = open_conn (& m_attr, m_buf, m_bufsize);} ~ connection () {close_conn (m_h DELETE M_BUF;}

Void Write (CHAR C) {WRITE_CONN (M_H, C);} char read () {return} (m_h);} ...

PRIVATE: Connection (Connection & Operator = (Const connection &);

"Well, very good, this question can be reported." SolmyR nodded, ready to leave, but stopped: "For Zero, Pisces, they have reported to increase people, from today's situation It is also really necessary to have someone who knows C to strengthen this. I see you just have time, this matter will be responsible. "

Zero's heart is secretly called, quickly distinguish: "No, Solmyr, I can't finish it now!"

"Yes? Oh ... Yes, I just received a report of the NMS, saying that there is a personal computer that has frequent access to QQ servers. Who is it?" SolmyR revealed his signature smile.

"Hey ... I thought about it, although I did more, the team's spirit is still to be carried out."

"Well, this is good." SolmyR left.

"I really see ghost!" After confirming SolmyR, Zero spit out the complaints in his heart: "It is difficult to have a hollow that you can rest, this is a soup! True to die." It's in Zero. At the time, a faint voice floated next to:

"Zero, what 'concept', 'concept', 'banned by SolmyR,', ', is it? Is you talking about it? Or you tell me ~~"

Zero turned his head and saw that Pisces looked at him in a very "sincere" eye, then thought of his future task, suddenly felt that his head was hidden - he seems to understand, why is it nothing? Solmyr is always in your own temple ...

转载请注明原文地址:https://www.9cbs.com/read-31548.html

New Post(0)