| 24小時(shí)熱門版塊排行榜 |
| 5 | 1/1 | 返回列表 |
| 查看: 1866 | 回復(fù): 5 | |||
| 當(dāng)前只顯示滿足指定條件的回帖,點(diǎn)擊這里查看本話題的所有回帖 | |||
cfem_nli新蟲 (初入文壇)
|
[交流]
【分享】在大的項(xiàng)目中為什么不用c++[也順便測(cè)試一下你的c++基本水平] 已有4人參與
|
||
|
語言之爭(zhēng)歷來有之,可謂是經(jīng)久不息. 大一統(tǒng)的原則在這里并不適用. 對(duì)于科學(xué)計(jì)算, 很多人一直在為c++做宣傳,為其翻身. 可是c++本身的缺點(diǎn)也是顯而易見的,太過于復(fù)雜,一個(gè)優(yōu)秀的c++程序員實(shí)在是不好找. 轉(zhuǎn)載一篇很久以前看到的文章, 從電腦里翻出來,忘了出處了, 哪位要是知道麻煩廣而告之. 看著篇文章,也順便測(cè)試一下你的c++基本水平. 這是英文原文,后面附帶了鏈接,可以下載.沒有時(shí)間做適當(dāng)?shù)姆g,如果哪位仁兄實(shí)在有此需要的話,我再盡量找時(shí)間補(bǔ)上;要是有人能夠翻譯了,在這里先行謝過了. 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 |

金蟲 (文壇精英)
老漢一枚
金蟲 (職業(yè)作家)

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

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

| 最具人氣熱帖推薦 [查看全部] | 作者 | 回/看 | 最后發(fā)表 | |
|---|---|---|---|---|
|
[考研] 求調(diào)劑,一志愿 南京航空航天大學(xué) ,080500材料科學(xué)與工程學(xué)碩,總分289分 +9 | @taotao 2026-03-29 | 9/450 |
|
|---|---|---|---|---|
|
[考研] 085701環(huán)境工程求調(diào)劑 +11 | 多久上課 2026-03-27 | 12/600 |
|
|
[考研] 求收留 +6 | 1943443204 2026-03-28 | 6/300 |
|
|
[考研] 生物學(xué) 296 求調(diào)劑 +5 | 朵朵- 2026-03-26 | 7/350 |
|
|
[考研] 0703化學(xué)321分求調(diào)劑 +10 | 三dd. 2026-03-30 | 11/550 |
|
|
[考研] 08工科,295,接受跨專業(yè)調(diào)劑 +3 | lmnlzy 2026-03-30 | 3/150 |
|
|
[考研] 342求調(diào)劑 +4 | 加油a李zs 2026-03-26 | 4/200 |
|
|
[考研] 生物技術(shù)與工程 +7 | 1294608413 2026-03-25 | 8/400 |
|
|
[考研] 311求調(diào)劑 +10 | lin0039 2026-03-26 | 10/500 |
|
|
[考研] 337求調(diào)劑 +6 | 《樹》 2026-03-29 | 6/300 |
|
|
[考研] 343求調(diào)劑085601 +3 | 要努力學(xué)習(xí)x 2026-03-29 | 3/150 |
|
|
[考研] 356求調(diào)劑 +3 | gysy?s?a 2026-03-28 | 3/150 |
|
|
[考研] 085701環(huán)境工程,267求調(diào)劑 +16 | minht 2026-03-26 | 16/800 |
|
|
[考研] 藥學(xué)105500求調(diào)劑 +3 | Ssun。。 2026-03-28 | 3/150 |
|
|
[考研] 339求調(diào)劑,想調(diào)回江蘇 +6 | 烤麥芽 2026-03-27 | 8/400 |
|
|
[考研] 張芳銘-中國農(nóng)業(yè)大學(xué)-環(huán)境工程專碩-298 +4 | 手機(jī)用戶 2026-03-26 | 4/200 |
|
|
[考研] 275求調(diào)劑 +10 | jjjjjjjjjjl 2026-03-27 | 10/500 |
|
|
[考研] 一志愿吉大071010,316分求調(diào)劑 +3 | xgbiknn 2026-03-27 | 3/150 |
|
|
[考研] 341求調(diào)劑 +7 | 青檸檬1 2026-03-26 | 7/350 |
|
|
[考研] 材料與化工304求B區(qū)調(diào)劑 +3 | 邱gl 2026-03-25 | 3/150 |
|