| 24小時(shí)熱門版塊排行榜 |
| 5 | 1/1 | 返回列表 |
| 查看: 1865 | 回復(fù): 5 | |||
| 當(dāng)前只顯示滿足指定條件的回帖,點(diǎn)擊這里查看本話題的所有回帖 | |||
cfem_nli新蟲 (初入文壇)
|
[交流]
【分享】在大的項(xiàng)目中為什么不用c++[也順便測(cè)試一下你的c++基本水平] 已有4人參與
|
||
|
語(yǔ)言之爭(zhēng)歷來(lái)有之,可謂是經(jīng)久不息. 大一統(tǒng)的原則在這里并不適用. 對(duì)于科學(xué)計(jì)算, 很多人一直在為c++做宣傳,為其翻身. 可是c++本身的缺點(diǎn)也是顯而易見的,太過(guò)于復(fù)雜,一個(gè)優(yōu)秀的c++程序員實(shí)在是不好找. 轉(zhuǎn)載一篇很久以前看到的文章, 從電腦里翻出來(lái),忘了出處了, 哪位要是知道麻煩廣而告之. 看著篇文章,也順便測(cè)試一下你的c++基本水平. 這是英文原文,后面附帶了鏈接,可以下載.沒(méi)有時(shí)間做適當(dāng)?shù)姆g,如果哪位仁兄實(shí)在有此需要的話,我再盡量找時(shí)間補(bǔ)上;要是有人能夠翻譯了,在這里先行謝過(guò)了. Why I Dislike C++ For Large Projects By Mark Roulo My primary complaint against C++ is that the language is so complicated, and has enough booby-traps, that average and above-average programmers have a difficult time writing code without serious bugs. In a large program with raw pointers, the quality of the program will largely be driven by the least talented members of the team. This makes it highly dangerous to select a language that requires all the programmers to be in, say, the top 25% of the talent pool. Given a team with 10 developers (and my projects typically have more like 40-50), this seems to be asking for lots of long term trouble. Things become even more unstable when one considers that the average turnover of software developers in Silicon Valley (where I live and work) is something like 20-25% and that many large projects also use contractors. The total number of programmers on a project will be much higher than the average (or even the peak) number of developers on the project. I have worked on a project with both C++ and Java components (roughly 50% each) that communicate via CORBA. Part of my job has been to interview candidates for both halves of the project over a period of several years. This has given me a fair amount of exposure to the C++ developer pool. As part of my standard interview for C++ candidates I ask them to write me a small class with the intention of evaluating their command of the language. This also gives us a reasonable coding sample to discuss during the interview. I can ask about potential improvements, extensions and testing strategies. Most of the candidates I interview have already made it to the top of the resume pool -- usually by claiming at least 3 years professional experience with C++. Since many resumes have this, the candidates tend to have some other plus: large systems experience, degree from a good school, personal recommendation, etc. The candidates then must survive a phone screen interview whose job is to weed out candidates that can't, for example, describe any of their projects coherently. My request is to: Write a Named Point class with three members: two floating point values for the coordinates on an X-Y plane, and a name represented as a 'char *'. Assume that this class will be used for some sort of wargame or simulation program that treats the world as flat and that these named points will be used to represent things like cities, battlefields, etc. A typical first try looks something like this: class NamedPoint { private: float x; float y; char *name; public: NamedPoint (float x, float y, char *name) { this->x = x; this->y = y; this->name = name; } float getX() {return x;} float getY() {return y;} char *getName() {return name;} void setX(float x) {this->x = x;} void setY(float y) {this->y = y;} void setName(char *name) {this->name = name;} }; There are several problems with this code: • name has its encapsulation violated with the getName() method. • The code calling the constructor is responsible for managing the scope of the member variable 'name'. This code fragment shows the problem: • // Ignore for now a lot of awfulness in this function ... • // this should probably be a constructor in a sub-class • // of NamedPoint, 'cityName' and 'countryName' should be • // checked for NULL _and_ for length so that sprintf() • // doesn't overrun temp ... • // • // The point is that if NamedPoint doesn't *own* its own • // 'name' value, the clients are at risk of memory corruption. • // • NamedPoint makeCityCoordinate (float x, float y, char *cityName, char *countryName) • { • char temp[80]; • sprintf (temp, "City: %s, Country: %s", cityName, countryName); • • return NamedPoint (x, y, temp); • } After I point out these problems, a typical fix is to modify NamedPoint to look like this (changes in bold): class NamedPoint { private: float x; float y; char *name; public: NamedPoint (float x, float y, char *name) { this->x = x; this->y = y; this->name = new char[strlen(name) + 1]; strcpy (this->name, name); } float getX() {return x;} float getY() {return y;} const char *getName() {return name;} void setX(float x) {this->x = x;} void setY(float y) {this->y = y;} void setName(char *name) {this->name = new char[strlen(name) + 1]; strcpy (this->name, name);} }; This trades in one set of bugs for another. The new version has the following problems: • It doesn't have a destructor, so it leaks memory. • setName() doesn't delete name, so it leaks more memory if setName() is called. • strlen(NULL) and strcpy(NULL) are bad. Usually, a program will crash if this is attempted, so we really should check for NULL. After I point this out, I usually get a third try that looks like this: class NamedPoint { private: float x; float y; char *name; public: NamedPoint (float x, float y, char *name) { this->x = x; this->y = y; if (name == NULL) this->name = NULL; else { this->name = new char[strlen(name) + 1]; strcpy (this->name, name); } } ~NamedPoint () { if (name != NULL) delete name; } float getX() {return x;} float getY() {return y;} const char *getName() {return name;} void setX(float x) {this->x = x;} void setY(float y) {this->y = y;} void setName(char *name) {if (this->name != NULL) delete this->name; if (name == NULL) this->name = NULL; else { this->name = new char[strlen(name) + 1]; strcpy (this->name, name); }} }; Things are slowly improving ... in the sense that the bugs are getting more and more subtle. It is also worth mentioning that over half of the candidates don't assign NULL to name if the input 'name' value is NULL, leaving the memory uninitialized. This really isn't a C++ issue. Failing to initialize pointers in C structs is equally bad. The new problems are: • NamedPoint allocates with 'new[]' but deletes with 'delete'. This may or may not work depending on the compiler. It seems to work fine for most current compilers, so I rarely comment on this. Still, it is incorrect. • Testing for NULL before calling delete is unnecessary (since 'delete 0' is defined to be harmless), but causes no damage other than slowing down the program slightly. • NamedPoint now trashes the heap if any NamedPoint objects are passed by value (like, for example, returning a NamedPoint object from a function). This is because the copy constructor that C++ gives us for free copies the 'name' pointer, but does not copy the contents. Now, calling the destructor on the first shared 'name' returns the memory to the heap (although the second copy will continue to use it, EVEN IF THE MEMORY GETS ALLOCATED TO SOME OTHER USE). Calling the destructor on the second shared 'name' probably corrupts the heap by deleting memory that was not, at that time, allocated (the second delete isn't required to corrupt the heap, but this is how most C++ heap managers work). • It has similar problems with the default assignment operator. After pointing out the copy constructor and assignment operator problems, the fourth try usually looks like the code below. But not always. Sometimes I need to explain to the candidates what a copy constructor and assignment operator are. Some candidates have strange beliefs about when you need to implement them. One candidate, for example, believed that copy constructors were needed for classes above some size threshold, but not needed for classes below that size threshold. I'll emphasise that I'm interviewing candidates with several years C++ experience who have already passes a phone screen. In any event, typical attempt number four: class NamedPoint { private: float x; float y; char *name; public: NamedPoint (float x, float y, char *name) { this->x = x; this->y = y; if (name == NULL) this->name = NULL; else { this->name = new char[strlen(name) + 1]; strcpy (this->name, name); } } ~NamedPoint () { if (name != NULL) delete name; } // NOTE: Most interviewees start with a signature // like this: // NamedPoint (NamedPoint copy) // NamedPoint (const NamedPoint & copy) { this->x = copy.x; this->y = copy.y; if (copy.name != NULL) { this->name = new char[strlen (copy.name) + 1]; strcpy (this->name, copy.name); } } NamedPoint & operator=(const NamedPoint & copy) { this->x = copy.x; this->y = copy.y; if (this->name != NULL) delete this->name; if (copy.name != NULL) { this->name = new char[strlen (copy.name) + 1]; strcpy (this->name, copy.name); } // Note that we haven't nulled out this->name, so // we can get a double-delete problem... } float getX() {return x;} float getY() {return y;} const char *getName() {return name;} void setX(float x) {this->x = x;} void setY(float y) {this->y = y;} void setName(char *name) {if (this->name != NULL) delete this->name; if (name == NULL) this->name = NULL; else { this->name = new char[strlen(name) + 1]; strcpy (this->name, name); }} }; This is almost correct! The big problems remaining are that the assignment operator doesn't check for assignment to itself, the copy constructor only partially copies if 'copy' has NULL for its name, and we still risk a double-delete via the assignment operator. If a program does try to assign one of these objects to itself, the object deletes its own 'name' value before attempting to copy it onto itself. I usually stop here (assuming we get this far). Conclusion Empirically, I have found it very difficult to find even experienced C++ programmers capable of correctly writing a simple C++ class containing a pointer. Since pointers are, because of the C legacy, an important part of the language, this is a fatal flaw for large projects that need to work. Summarizing the mistakes in my fairly trivial problem: • Pointer assignment (a C legacy) makes it too easy to corrupt the stack and heap. The initial solution allows the stack to be accessed after it has gone out of scope. Corrected versions often allow for double deletes of heap allocated storage or accessing already deleted heap storage or both. • The default copy constructor and assignment operator are too often wrong. But you get them unless you explicitly take action. The language default being fatally wrong is a big problem. • delete and delete[] are similar, but possibly different. • NULL is legal for many pointer values, but the behavior tends to be undefined (delete being one nice exception). Since the NULL case is frequently overlooked, memory corruption again seems to be designed in to large systems. One solution is to do a lot more stuff with things like STL string objects and generally try to hide the heap allocation. The auto_ptr<> and similar classes help here, too. But they only help. The fundamental problem still remains -- it is too easy to write subtly wrong code and the language is littered with booby-traps. Larger programs encounter even more tricky problems. Scott Meyers has written two book on the subject of not getting killed by the C++ language. My point, though, is that most experienced C++ programmers I have interviewed can't get a simple class correct, even after multiple tries. Enough said. It makes me unwilling to risk a large project with the language. http://dl.dropbox.com/u/1982439/CAE%20software%20development/Programming/Language%20arguments/Why%20I%20Dislike%20C%2B%2B%20For%20Large%20Projects.doc |

新蟲 (初入文壇)
|
我想可能讓你有所誤會(huì)了。 首先呢,想說(shuō)幾句題外的話,歷來(lái)的語(yǔ)言之爭(zhēng),其實(shí)乏味,大都是各領(lǐng)域的頂尖的一些人物,在那里宣傳自己的種種好處,對(duì)我們來(lái)說(shuō),這樣的爭(zhēng)辯本身沒(méi)有意思,但是呢,可以看到一些語(yǔ)言的基本的但是很深層次的東西,缺點(diǎn)或者是優(yōu)點(diǎn); 其次,如果要辯論,那么也是看應(yīng)用背景,就是說(shuō)我們要做什么樣的應(yīng)用開發(fā),說(shuō)白了,具體應(yīng)用具體分析,沒(méi)有大一統(tǒng)的語(yǔ)言 再三,稍微通用一些的層次上,比如說(shuō)很多人包括我自己當(dāng)時(shí)就問(wèn)應(yīng)該學(xué)什么語(yǔ)言好,如果說(shuō)一定是要給點(diǎn)說(shuō)法的話,那么,個(gè)人以為容易上手是一個(gè)首要的法則。就是說(shuō),對(duì)初學(xué)者,對(duì)一般層次的人,比如說(shuō)本人,學(xué)的來(lái),但是呢又不容易犯錯(cuò)。 關(guān)于我自己,其實(shí)非編程的科班出身,也不敢自認(rèn)為高手,力學(xué)出身。做這樣的思考,是因?yàn)楫?dāng)要作有限元軟件開發(fā)的話,想比較比較那些語(yǔ)言在那些方面有優(yōu)勢(shì),為什么現(xiàn)在的軟件是現(xiàn)在這樣的結(jié)構(gòu)構(gòu)成,等等問(wèn)題。這樣的背景,極有可能讓我想問(wèn)題的方式有偏頗,對(duì)語(yǔ)言的看法也來(lái)的不如程序高手那么直接和簡(jiǎn)潔,一語(yǔ)中的。 說(shuō)了不少,回到先前的帖子上。英文原文的一些看法讓我深以為然,兩個(gè)原因,一個(gè)是:他涉及到了c++的構(gòu)造函數(shù),再一個(gè)是她說(shuō)到的是項(xiàng)目開發(fā)的實(shí)際情況。對(duì)我己而言,不是編程特多,c++的構(gòu)造函數(shù)很讓我頭疼,尤其是涉及到繼承以后,構(gòu)造函數(shù)很多類別,構(gòu)造函數(shù)里的函數(shù)變量定義,初始化,exception handle,指針處理,不少的問(wèn)題,讓我感覺(jué)應(yīng)付來(lái)有點(diǎn)頭疼,覺(jué)著需要很多練習(xí)才行; 這是他說(shuō)的第一個(gè)方面 。關(guān)于指針的話,我想,他沒(méi)有提多少,但是估計(jì)讓不少人構(gòu)頭疼的吧 第二個(gè)就是,實(shí)際做一個(gè)項(xiàng)目來(lái)說(shuō),就有很多的人來(lái)做。Top10 或者top20,在你的組里,是個(gè)好事,不過(guò)有一個(gè)差一些的也在做,那么可想而知你的麻煩事一定是源源不絕。很遺憾的是,那個(gè)造成這種局面的人往往意識(shí)不到那些潛在的錯(cuò)誤。 至于說(shuō)原帖那些都應(yīng)該是c++的基礎(chǔ),或者說(shuō)學(xué)過(guò)c++的人都該知道的,我不知道實(shí)際情況,我不知道怎么定義c++的基礎(chǔ)內(nèi)容;蛟S最好能做一個(gè)統(tǒng)計(jì),看看大家常見的錯(cuò)誤,或者令程序員們常常痛恨的錯(cuò)誤,等等 但是并不是要來(lái)否定c++,linus說(shuō)C++ Sucks,我不知道,沒(méi)有他那么偏激。 歡迎有想的想法,歡迎指正。 |

金蟲 (職業(yè)作家)

金蟲 (文壇精英)
老漢一枚
新蟲 (初入文壇)
|
首先呢,這個(gè)鏈接有點(diǎn)感覺(jué)是偏離主題了,只不過(guò)是我上面的帖子提到了這個(gè),所以就權(quán)作為娛樂(lè)休閑,想看的朋友就關(guān)注一下 不想就這個(gè)作為討論,實(shí)在是力不從心 我個(gè)人覺(jué)得之所以他那么偏激,可能一是他自己是一個(gè)c的fan,二是c當(dāng)時(shí)是為系統(tǒng)開發(fā)而做的,可能就是適合linux kernel吧,印象中記得他說(shuō)c++ 是在c上添枝加葉,盡做些不痛不癢的修改,說(shuō)來(lái)說(shuō)去,都不乏炒作之嫌 http://thread.gmane.org/gmane.comp.version-control.git/57918 why c++ sucks by linus |

| 最具人氣熱帖推薦 [查看全部] | 作者 | 回/看 | 最后發(fā)表 | |
|---|---|---|---|---|
|
[考研] 環(huán)境工程 085701,267求調(diào)劑 +9 | minht 2026-03-29 | 9/450 |
|
|---|---|---|---|---|
|
[考研] 311求調(diào)劑一志愿合肥工業(yè)大學(xué) +5 | 秋二十二 2026-03-30 | 5/250 |
|
|
[考研] 285求調(diào)劑 +6 | AZMK 2026-03-29 | 9/450 |
|
|
[考研] 11408總分309,一志愿東南大學(xué)求調(diào)劑,不挑專業(yè) +5 | 天賦帶到THU 2026-03-29 | 6/300 |
|
|
[考研] 材料工程專碩求調(diào)劑 +8 | hyl3153942 2026-03-29 | 8/400 |
|
|
[考研] 一志愿南昌大學(xué)324求調(diào)劑 +9 | hanamiko 2026-03-27 | 9/450 |
|
|
[考研] 材料化工340求調(diào)劑 +3 | jhx777 2026-03-30 | 3/150 |
|
|
[考研] 化學(xué)0703 調(diào)劑 306分 一志愿211 +8 | 26要上岸 2026-03-28 | 8/400 |
|
|
[考研] 342求調(diào)劑 +4 | 加油a李zs 2026-03-26 | 4/200 |
|
|
[考研] 0703 化學(xué) 求調(diào)劑,一志愿山東大學(xué) 342 分 +7 | Shern—- 2026-03-28 | 7/350 |
|
|
[考研] 303求調(diào)劑 +7 | DLkz1314. 2026-03-30 | 7/350 |
|
|
[考研] 329求調(diào)劑,一志愿西北工業(yè)大學(xué),材料工程(085601) +5 | 小小機(jī)靈蟲 2026-03-29 | 11/550 |
|
|
[考研] 070300化學(xué)354求調(diào)劑 +7 | 101次希望 2026-03-28 | 7/350 |
|
|
[考研] 283求調(diào)劑(080500) +14 | A child 2026-03-27 | 14/700 |
|
|
[考研] 化學(xué)工程085602 305分求調(diào)劑 +25 | RichLi_ 2026-03-25 | 25/1250 |
|
|
[考研] 材料與化工272求調(diào)劑 +21 | 阿斯蒂芬2004 2026-03-28 | 21/1050 |
|
|
[考研] 070300求調(diào)劑306分 +4 | 26要上岸 2026-03-27 | 4/200 |
|
|
[考研] 295求調(diào)劑 +5 | 1428151015 2026-03-27 | 6/300 |
|
|
[考研] 266分求材料化工冶金礦業(yè)等專業(yè)的調(diào)劑 +4 | 哇呼哼呼哼 2026-03-26 | 4/200 |
|
|
[考研] 305求調(diào)劑 +5 | 哇盧卡庫(kù) 2026-03-26 | 5/250 |
|