×

Loading...

You just don't get how powerful template can be, do you? STL is just one example of template applications

本文发表在 rolia.net 枫下论坛I've backed my words by demonstrating my code and solving your problem : a tree which supoprts degree 4. That's enough. If you don't get it, that's your problem.
"the node of tree has a pointer to its parent"? And you asked " I guess you must have good time make it happen. "? Dude, you are funny. Yes, it must take the rest of my whole life to add one line code! LOL!!!
And "move the node from memory to harddrive"?
Regardless the details, say file I/O, or in fancy terms, serializing,
What do you want to prove?
Do you really understand what generic programming is for? It's not magic, it 's not for everything, can you find me where I've said anything remotely close to that please?
All I've been saying is that C++ template enables you to write one generic code for any given algorithm/data structure, regardless the type of elements in containers.
Whether you get my point or not, I'll have to end the discussion with you.
It has been pleasant talking to you. :-)更多精彩文章及讨论,请光临枫下论坛 rolia.net
Sign in and Reply Report

Replies, comments and Discussions:

  • 工作学习 / 专业知识杂谈 / 学习怎样用别人的轮子,别重新发明轮子 ---- 从用不用STL往远了扯
    本文发表在 rolia.net 枫下论坛单打独斗的hacker时代早就过去了,软件实现的功能越来越复杂,绝大多数的软件开发都是team work。这是谈用不用STL的前提。

    自己写STL的部分功能还是有好处的,你不用学STL,你知道你写的程序怎么用而不用读任何文档,接口都在你脑子里,它能处理什么不能处理什么你都清楚。自己写这些功能也不很费劲,因为都是自己用,你不必把它写得很完善,能满足自己的需要就行了。
    在一个team的环境,某甲需要用到STL中的某个功能他不用,甲自己实现;乙需要用到另外一个部分,乙自己实现;丙需要用和甲同样的部分,丙也自己实现...不同的人都实现了STL的功能子集,这些代码分散在系统的各处,并且存在功能重叠。lead怎么能容忍这样的事情发生?OK,你们把这些STL的功能子集都从每个人的程序中分离出来,放到一起,合并重叠的部分。now what happened?自己开发功能子集的好处没有了。在写自己这块的时候,每个人必须把自己的这块弄得很完善,要能handle各种情况,有详尽的文档,约定都必须是显式的...在用别人写的那块的时候,你得读别人的文档。如果项目足够大,你们最后就在开发自己的STL... 重新发明轮子。因为项目组的人员水平参差不齐,你们重新发明了一个方的轮子!然后某甲离开了team另谋高就了,某丁加入了这个team。now what? 尽管某丁在别的公司天天用STL,现在他必须要学习这个内部版的STL替代品怎么用!

    这只是我编的一个故事,发生的可能性存在但是不大,因为大多数人还是会用STL的。可是如果不是STL这样低层的东西,而是中间层面的呢?原意自己实现而不用现成solution的人还是很多,看看有多少种web framework就应该有概念了吧。以前我工作过的某个公司做电子政务的,小到数据库连接池,大到工作流引擎,全都是自己写。我现在工作的公司做Premium Financing系统,有自己的web framework,自己的ORM,自己的软件源程序生成器!
    别误会,我不是在说他们有多牛,我想说他们有多错。在最初开发这些东西的时候,我相信他们是很爽的,自己写的framework,想怎么用就怎么写,多爽啊,不用学现在流行的只听过名字不知道意思的东西。但是,一些需求,有些是他们当初忽略了,有些是当时没有,今天都冒了出来。作为后来的人的就必须要维护这些,这是极不爽的工作。
    有些比较简单了,比如说原来生成的代码没有足够的logging,系统投产以后出现问题很难support,OK,看懂原来的代码生成器怎么工作的,加生成logging的代码进去,no big deal。可是有些东西就很讨厌,比如说现在要给系统加ajax支持,本来写个简单的ajax框架并不很难,可是卡在安全性这块了。这个框架的用户认证是在主控servlet中,用一个UserManager往ThreadLocal写东西;而很多业务代码对这个UserManager有依赖。要给这个framework加ajax支持,必须先在业务逻辑和UserManager之间解耦,再把用户认证从主控中抽出来,用AOP用拦截或者用filter来实现。难倒不难,可是牵涉到业务层的很多类,工作量很大。
    并不是说用opensoure的框架就完全不会有这样的问题,但在opensource的框架中,你能遇到的问题常常是别人先遇到,并且常常已经有解决方案。实际上,具体到ajax支持,假设我们以前的team选择了流行的开源框架(struts, spring, jsf),现在我再拿个开源的ajax框架(dwr),这两个框架之间如何集成有现成的solution,我只要看看文档就行了。甚至,用户认证这部分也有现成的方案(acegi)。
    学习和使用别人的轮子,有时候不一定是产品,有时候是pattern。我们现在用的ORM是以前的team做的,从一个XML描述文件,对每个数据库表产生一个interface/class对,另外有个DBManager类来做数据库操作。程序中对table的访问实际是面向接口的。因为种种原因我们现在想要把系统移植到hibernate上。如果,唉,如果以前的team在实现的时候用了DAO pattern,我现在的工作就要简单得多。我已经实现了从原来的描述文件生成hbm,从model object生成hibernate DAO的工具到处都是,可原来的设计不follow DAO pattern,就多出来很多工作要做。
    我现在做的这个系统,如果都用现成的东西,有四五个经验丰富的程序员,需求基本明确的情况下,4到6个月第一个release,再有2,3个月就能稳定。而实际上呢,因为很多精力都消耗在框架上,做了差不多两年,才算有了可以release的版本,而且还不够稳定。

    每一个软件开发人员都有自己应该面对的domain problem,善用现成的东西,能帮你focus在自己的domain problem上。新东西层出不穷,要想善用,没办法,学吧!

    与诸君共勉更多精彩文章及讨论,请光临枫下论坛 rolia.net
    • 什么是STL?
      • C++的东西吧,好像是用C++的template实现的
      • Standard Template Library
    • 写得不错
    • 说起来容易,做起来太难。
      • 谢谢支持.
    • 如果就是一般链表,栈这些3,2条语句就解决的简单数据结构用stl还不够麻烦的。用不用是architect决定,tl和一般组员要决定这个吗?
      • 谢谢支持.
        • 请你用代码例子解释一下如何用两三条自己的语句实现链表,还有STL为何不能用两三条语句来实现
          • 比如说把一个节点添加到表头这个函数就3,2句,很简单直观,自己写一个链表template应该不要花很久,如果你只用这么简单的数据结构,自己写一个好处多多。如果已经决定了,别人也已经用了,那就随大流了。
            CList::InsertFirst(CNode* pNode)
            {
            //if pnode != NULL
            if(m_pFirstNode != NULL)
            {
            pNode->pNext = m_pFirstNode;
            m_pFirstNode->pPrev = pNode;
            }
            m_pFirstNode = pNode;
            }
            • stl只需要一行就搞定了list<CNode*>
              • 你跟我讲的不是一回事。我讲的是list template的实现,写得好的template代码肯定比stl的简洁,因为你只需要实现你要的功能。你讲的是怎么使用,直接用stl或者用自己写template,从使用这个角度来讲,是没用区别的。
                • 不明白,你自己就算能写出来,又有什么用呢?别人不能用,因为功能不全,你不干了,别人维护更麻烦
                  • 一个链表左右不过是在头上加个节点,在尾上加个节点,在某个节点前/后加节点,删节点,找节点,谈得上什么维护?你一天加一个功能,加个7/8天就没什么可加的了,以后就永远不用动了。
                    • 请为你的LINK/MAP/LIST实现以下最简单的接口
                      本文发表在 rolia.net 枫下论坛Member Functions
                      assign
                      Erases a vector and copies the specified elements to the empty vector.

                      at
                      Returns a reference to the element at a specified location in the vector.

                      back
                      Returns a reference to the last element of the vector.

                      begin
                      Returns a random-access iterator to the first element in the container.

                      capacity
                      Returns the number of elements that the vector could contain without allocating more storage.

                      clear
                      Erases the elements of the vector.

                      empty
                      Tests if the vector container is empty.

                      end
                      Returns a random-access iterator that points just beyond the end of the vector.

                      erase
                      Removes an element or a range of elements in a vector from specified positions.

                      front
                      Returns a reference to the first element in a vector.

                      get_allocator
                      Returns an object to the allocator class used by a vector.

                      insert
                      Inserts an element or a number of elements into the vector at a specified position.

                      max_size
                      Returns the maximum length of the vector.

                      pop_back
                      Deletes the element at the end of the vector.

                      push_back
                      Add an element to the end of the vector.

                      rbegin
                      Returns an iterator to the first element in a reversed vector.

                      rend
                      Returns an iterator to the end of a reversed vector.

                      resize
                      Specifies a new size for a vector.

                      reserve
                      Reserves a minimum length of storage for a vector object.

                      size
                      Returns the number of elements in the vector.

                      swap
                      Exchanges the elements of two vectors.

                      Operators
                      operator[]
                      Returns a reference to the vector element at a specified position.更多精彩文章及讨论,请光临枫下论坛 rolia.net
                      • 我试试
                        大概就是一个vector类
                        类里有成员变量:
                        pNode; // 指向vector块的第一个元素
                        capacity;//最多能容纳多少元素1based
                        count; //实际多少元素1based
                        有这么一个成员函数
                        xxxx(index)
                        {
                        return pNode+index-1;
                        }

                        你要的那些个功能里面有好些个,只要调这个函数就能实现了
                        比如
                        at(index) 直接调xxxx(index)
                        operator[下标]直接调xxxx(下标+1)
                        back()直接调xxxx(count)
                        front()直接调xxxx(1)

                        max_size/capacity/size直接返回成员变量的值就可以了
                        push_back就是给xxxx(count)元素赋值;count++;
                        pop_back就是count--
                        swap(index1,index2)就是交换xxxx(index1)和xxxx(index2)返回的2元素的值。
                        insert(index)麻烦一点,memcpy(xxxx(index), xxxx(Index+1), sizeof(pNode) * (count-index)); pNode[index]赋值;count++;
                        那些iterator函数只要添一个成员变量就可以了
                        再加上一些下标溢出检查什么的
                        大概就这样吧
                        • A couple of problems in your solution
                          本文发表在 rolia.net 枫下论坛1) a very easy one, method swap has the following signature
                          void swap(vector&); it's to swap the contents of two vectors, not to swap two elements
                          Can you provide pseudo-code for swap?

                          2) your insert method has a few problems,
                          a correct sequence of action ( suppose there is avaialbe space in vector) is like following
                          _Construct(_M_finish, *(_M_finish - 1));
                          ++_M_finish;
                          _Tp __x_copy = __x;
                          copy_backward(__position, iterator(_M_finish - 2), iterator(_M_finish- 1));
                          *__position = __x_copy;

                          a) the first step is to construct a new object at the current end with placement new, if it succeeds, then increase the counter, otherwise if there is an exception, it will throw and the internal status of the vector is unchanged, thus exception-safe.
                          you CANNOT call memcpy instead of constructing simply because wherever the current end is, there should be no constructed object there ( if there was one there before, when pop_back is called, you should call destructor explicitly to destroy the ojbect at that location, and decrease the counter), therefore you have to call constructor to do the job. Plus, you CANNOT assume constructor does the same thing as bitwise memory copy in this situation
                          b) you CANNOT use memcpy to right shift the objects whose indices are bigger than the insert position, for the same reason as above. Instead, operator=() should be called to do the work. operator=() is NOT always bitwise copy.
                          If you read STL source code ( a little gibberish), you'll see that it's very smart. It uses template partial specialization and type traits to dispatch/optimize the code.
                          Simply speaking, it checks whether type T has trivial assignment operator=, if yes, it 'll use memmove to shift the objects, which is faster than memcpy. If no, then it will use a loop to call assignment operator= .
                          By default, the template traits has NO trivial assignment operator. However, it defines traits for builtin type like int, double etc to have trivial assignment operator so that those types can be optimized to memmove. So if you want to use memmove to optimize copy for your own type T, suppose operator= does the same thing as memcpy, then you can define traits for T

                          I don't know others, but to me it's a lot more difficult to write your own container (bug free, scalable and efficient in size and speed) than it seems, especially considering exception-safe. I hate to be a C++ programmer, LOL.更多精彩文章及讨论,请光临枫下论坛 rolia.net
                          • 我提供的只是insert的逻辑,它不是通用函数不能处理直接所有的情况,用memcpy代替construct来处理没有构造和析构的简单节点类(比如说字串,结构)是没有任何问题的。如果说有一天你想要实现一个更复杂的节点类,
                            你可以通过template specialization方法重写insert或者别的函数,这正是自己写template的好处:你需要什么就实现什么,有完全的控制,而不是用的没用的都连进来。

                            我不是要提供一个完美的方案,也不是要用我的方法挑战STL的。
                            • Guess we need to agree to disagree :-)
                              本文发表在 rolia.net 枫下论坛I understand your point and respect that.
                              However I insist that vector is supposed to be a generic container, therefore insert() method should also be able to handle any type, not only primitive tpes like int, char. And as we've seen, it truly takes more than a couple of lines to implement a vector class.
                              I'm not saying that you can't write your own stuff, especially something of special requirement and not available yet in library. However, if you ask me, I wouldn't write my own version of common containers like stack, list or vector, because of two reasons
                              1) Most importantly, I want my code easier to read/maintain for others
                              2) I'm not confident that my containers will be better than STL :-), especially after spending some time reading exceptional/more exceptional C++ and STL source code, then realizing so many things I don't know, and sweating a lot

                              On a side note, I don't think it's correct to say when you use STL, the binary size grows bigger mostly because of the linked libraries. After all, STL or C++ template code, are just a bunch of header files ( even they can be named .c, .cc sometimes), nothing more than smart macro. Before you instantiate them, they only contain pseudo code, only when you instantiate it, the compiler generates real code. IMO template inflation caused by instantiation is mainly responsible for this, not linked library.

                              However, this is almost unavoidable due to the nature of C++ template. Even if somebody writes his own template version with the same functionalities of STL, I doubt it can do much better than STL. Actually the STL source code is quite smart to me when it comes to reducing template inflation. It exacts the non-generic , i.e. variable/method of fixed type/signature, and create non-template base class to encapsulate them, then the generic class template inherits from them, thus reduce the code size inflation.更多精彩文章及讨论,请光临枫下论坛 rolia.net
                              • 我对STL没有抵触情绪,该用还是得用
                                1. 通用性是那些提供STL的人要考虑的,越通用,用的人就越多。对于STL用户来讲,我们希望有个量身定做的STL,只实现需要的功能。不需要的那些功能对你没有任何用处,除了增加可执行文件的长度。(只要你用了STL的类,该类的所有成员变量和函数,用到的没用到的,都会被连到可执行文件中,这当然会增加长度)

                                2. 实际应用中,通用性再好也是不够的,你有时候还是要自己写。timhorton举的例子为了实现skiplist自己写了个双向链表,我不知道他具体怎么实现的,但是可以肯定的是:1 绝大部分函数和STL的重复了。如果你自己写template, 这些函数是可以重用的。 2 你有2套接口,一套是STL,一套是自己的双向链表,相比自己写的只有一套接口那个更易读?不说别的,光给这类起个好名字就够头痛的了。

                                你英文很棒啊,是在这里上的大学吗?
                          • Can you provide pseudo-code for swap(vector&)? 我不明白为什么会有人需要这么样一个功能?
                            我以为是要swap vector里面的2个元素, swap2个vector太奇怪了,我不明白为什么会需要这么一个函数?

                            我猜想大概是这样吧?
                            vector a;
                            vector b;
                            <...>
                            a.swap(b);

                            为什么不作成这样:
                            vector * a;
                            vector * b;
                            a = new vector;
                            b = new vector;
                            <...>
                            vector *temp = a;
                            a = b;
                            b = temp;
                            这岂不是又快又爽?
                            • Interesting question, I was thinking about it too :-)
                              本文发表在 rolia.net 枫下论坛First, it is different to swap two pointers vector * a, *b;
                              and two vectors vector a, b
                              The former doesn't change the two vector objects pointed to by a and b, it just changes the pointers, while the latter swaps the contents of the two vectors. what if users really need to do the latter?

                              Second, the member function vector::swap(vector&) can be done in constant time, because it only swaps some member variables of primitive types, usually just pointers to the start, finish and end_of_storage of the memory block allocated for vector, or/and counter.
                              As a result, if you have two vectors a and b, and you want to assign b to a efficiently, and you don't need b anymore, then swap is a lot faster than operator=, which (probably) needs to allocate memory ( if b is bigger than a), construct every object from b to the new memory location, then destroy everything in old a.

                              Last, since swap primitive types, say pointers, integers etc, never throws, swap is exception-safe. when you assign b to a, you create a temporary copy of b first, say c, if it succeeds, then you know you can swap c and a and there will be no exception thrown. If construction of c fails, then a is not affected, therefore safe.更多精彩文章及讨论,请光临枫下论坛 rolia.net
                              • 我还是不能理解为什么需要这个函数。如果是java不支持指针我可以理解。但是现在是c++
                                #1 所有需要“交换2个vector内部所有元素”的地方都可以改用“直接交换2个vector的指针”来实现。放着直接交换指针这种最简单有效的方法不用,采用交换内容的方法,是没有道理的。
                                #2 “swaps some member variables of primitive types”当然很好,但是不同的节点类型要交换的成员变量不同,这意味着不同节点类型需要不同的swap。如果采用直接交换vector指针的方法,你根本不需要关心节点类型。
                                #3 交换指针也是exception-safe的。
                                vector *a; vector *b;
                                a = b;是简单的赋值语句,不需要创建temporary copy of b。
                                • what if we have two global or static or local ojbects vector a,b, i.e. not allocated by new, and we want to swap the contents of them?
                                  e.g,
                                  vector<int> a, b; //two vector objects not allocated by new, you CANNOT assume users always use new, e.g. vector<int> * a = new vector<int>, right?
                                  What if users want to swap the contents of a and b now? Can you do this?
                                  vector<int>* aptr = &a;
                                  vector<int>* bptr = &b;
                                  then swap aptr and bptr?

                                  No, swap pointer doesn't fit the requirement here. It is useful in many cases, as you mentioned, and can do the same job as swap in certain situations, but it cannot replace swap.

                                  The global swap function in namespace std, std::swap(vector& a, vector& b) is based on the member function swap of vector. std::swap(a,b) is translated into a.swap(b). It's quite common in the standard library code.
                                  • 如果你需要交换,一开始就应该设计成global/static/local指针, 动态分配/删除!
                                    e.g,
                                    vector<int> a, b; //two vector objects not allocated by new, you CANNOT assume users always use new, e.g. vector<int> * a = new vector<int>, right?
                                    What if users want to swap the contents of a and b now? Can you do this?
                                    vector<int>* aptr = &a;
                                    vector<int>* bptr = &b;
                                    then swap aptr and bptr?

                                    No, swap pointer doesn't fit the requirement here. It is useful in many cases, as you mentioned, and can do the same job as swap in certain situations, but it cannot replace swap.
                                    =========================================================
                                    你说的user其实是C++程序员,如果我是他的leader,我要问问他为什么非要这么用!为什么不用指针。
                                    如果我自己写template,我不提供这个swap函数,用这个vector的C++程序员根本不会产生这个想法。
                                    • I kinda agree with you on that swap is not used that often by us librariy users, at least from my experience.
                                      本文发表在 rolia.net 枫下论坛But I noticed that it's used quite often to implement other methods in STL.
                                      Think about this, you have a vector like this
                                      template < typename T>
                                      class vector {
                                      T* start, *finish, *end_of_storage;

                                      T& operator=(const T& rhs);
                                      ... ...
                                      }

                                      How do you implement operator=?, don't forget exception safety here.
                                      When you call operator=, the caller object has been constructed before that, i.e. "this" pointer is fixed, can't be changed, right?
                                      Can you destroy objects in the caller vector first, then copy construct every object from the vector rhs? No, think about it. What if one of the constructor calls fails?
                                      swap() can be handy in this situation.
                                      You can create a local object within operator=(), say C, and call swap() to swap the member variables : pointers, of C and *this, when operator= returns, C will be cleared automically as well as the objects inside C

                                      Sorry, I can't post on this issue anymore. Lots of other things to do.
                                      Anyway I recommend you to read exceptional C++ and more exceptional C++, they have some in-depth analysis about swap() function. Very intersting books, but too difficult to me at times. We can discuss this in PM if you want, I'm a C/C++, Unix programmer coming from C. I like to learn together and improve together with buddies. Thanks for posting your thoughts, it's always a good thing to hear other people's opinions.更多精彩文章及讨论,请光临枫下论坛 rolia.net
                                      • 也谢谢你
                                        我还想说2句,拷贝构造函数里面是不能调用你这个swap的,因为这样的话,你把b的那个pNode的指针保存到了a里面了,一个指针保存到了2个instances里面,这2个instances dtor的时候就会2次释放同一个指针。
                                        拷贝构造函数里面是不能偷懒的,必须重新分配pNode,然后老老实实把数据从b里面拷过来。
                                      • My bad, T& operator=(const T& rhs) should be vector& operator=(const vector& rhs)
                                • Concept error -> '如果是java不支持指针我可以理解". Virtually there is no difference of swapping pointers in C++ and swapping references in Java.
                                  • 引用就是const的指针。如果你访问他们所指向的类的成员,他们是没有区别的。但是指针可以被修改指向任何地方,引用不行。所以你在java里不可能是实现 vector *a,*b; a=b;的。
                                    我觉得你对指针和引用的区别不是很清楚。
                                    • Two things you can trust me. First, I'm not homosexual, lol. Second, you are confused with C++ reference and Java reference
                                      What you described is C++ reference, which is basically a pointer whose value can't be modified once initialized, regardless the syntax

                                      Java reference is not the same, try compile & run this code

                                      import java.util.Vector;

                                      class test {
                                      static void main(String[] args) {
                                      Vector a = new Vector();
                                      Vector b = new Vector();
                                      Vector temp = a;
                                      a = b;
                                      b = temp;
                                      }
                                      };
                                      • 我以后有机会试试看
                        • You answer may not satisfy the time cost requirements for the operations on vectors.
                          There are time cost requirements for the operations on vectors. For example, an insert should cost almost O(n) where n is the number of elements in the vector. In your answer, if the sizeof(T) is very big, the time cost is too big. To solve this issue, the objects of T are not directly stored in the array, but the address of the objects. So when you move objects, you only move the the pointers whose size is 4 in 32-bit machine. Thus the time cost can fulfill the requirements.
          • 这个问题用代码解释不了。你得先看看有什么库可以用,有些库是要花钱的。即使有,能不能用也先要测试后由team来决定。如果你在项目中擅自联接进来什么库的话,问题就大了,代码段可能会增加1M以上,
            在有些项目,1M以上的变化会带来大量的确认工作。此外,通用STL也会造成运行速度的下降,信不信由你。我以前的一个项目先用的AT&T的STL,后来不得不写我们自己的库。很多鼓吹STL不会增加运行开销的书都是胡扯。我在EA的一次面试里被问到过STL,当我说了自己的感受之后,EA很激动地说他们早就开始不用通用STL了。
            再说说重用。坛子里的柳五随风说过面向对象要从analysis到design,此话很精练。我想只有厌恶过面向对象的人才能真正理解这是为什么。
            • 做游戏肯定不喜欢通用的东西,不要说STL,memcpy还要重写几种版本来支持不同的CPU加速。LZ的代码重用的概念也是没有错的,只是过犹不及,人人都用现成轮子,不造新轮子,恐怕现在汽车还在用木头轮子。
              • 是啊,我对LZ坚决支持。但是实际项目中等真正搞明白设计是否合理往往太晚太晚了。使用面向对象时这种感觉尤其明显,这就是为什么先要分析透彻的原因,可惜这一点是最难做到的,有时候是不可能的事情。
            • 你不会还生活在石器时代吧?
              • .
      • 我不是在说,今天我要写个小程序,需要用到链表,我是自己实现还是用STL,不是这样的。我说的是在一个team的环境里,做一个实际的项目,今天我要用到链表,明天要用到栈,后天还要用到其它,我的同事和我一样有这样的状况...
        • 我也用到单双向链表,栈,但是我不会因此就使用stl,我真的觉得是没有必要。如果你要用到图,数,向量这些东西的话就是另一回事了。
          • 数=树
        • 链表,栈,树,MAP,所有东西都在STL里面用最高性能实现了,我看不出你这样用法有什么实际意思.我自己也写DUALLINK,不过用途是MMAP文件后,用链表和skip list进行内存分配和虚拟内存映射.STL里面没有的功能我才自己写
          • 我对此表示怀疑,STL为了保证通用性,亢余无用代码是不可避免的。你举的例子我不太明白,skip list不是单向的吗?但是我感觉你现在这种情况用stl没得到什么好处,因为你还是要自己维护一个双向链表。
          • 给我一个STL的TREE.另外,我还想B TREE.我可以用C写一个,您就用STL写一个,如何?至于图的话,我以前写了一些,但是不好,但是,你的STL能写吗?这么简单的STL,想想这世界的存在DATA STRUCTRUE的复杂度再说吧.
            • 你是不是根本不知道STL是什么吧?---我可以用C写一个,您就用STL写一个,如何?---太无知了吧?
              • .
            • don't you know that map/set in STL are all trees, red-black trees in most implementation?
              • Then write a simple TREE that support a degree of 4. By the way, please pay attention to what is abstract structure and physical structure.
                • Put it this way, whatever data structure/algorithm you do in C, it can be done generically with C++ template thanks to the compiler
                  Actually it is the original purpose of template, to make data structure/algorithm programming generic. Anyway I'm not an expert on data structure. Can you post your code in C so we can take a look?

                  Sorry if my previous posts offended you.
                  • A tree in C? Yes, I want to spend the time to power up the 10 year old computer. this task is simple for every good computer science student.
                    on the other hand, this code is available as C code everywhere if you would like to google it.
                    • Here my answer is, you'll see how simple it is to support tree with any type T and any degree thanks to C++ template
                      本文发表在 rolia.net 枫下论坛template <int X, typename T>
                      struct Node {
                      T value;
                      Node* children[X];

                      void initChildren() {
                      for(int i=0; i<X; i++) {
                      children[i]=NULL;
                      }
                      }

                      Node(T tmpvalue) : value(tmpvalue) {
                      initChildren();
                      }

                      Node() {
                      initChildren();
                      }
                      };


                      template <int X, typename T>
                      class Tree {
                      private :
                      typedef Node<X,T> treeNode;

                      treeNode header;


                      /*
                      add whatever methods here, whose logic is about the same as the countper part in C, insert, delete, traverse etc
                      */
                      };

                      This is the basic look of the tree class, which supports any type of element T
                      and any degree X. I didn't bother finishing the rest of the code as
                      it is quite straightforward. in your case, you want degree up to 4, and suppose you want a tree of int, then just instantiate it like this

                      typedef Tree<4,int> DegreeFourIntTree; // typedef to make it less confusing
                      DegreeFourIntTree tmptree;


                      yes, just this simple

                      BTW, as silly as it may sound, when I first read your question, I didn't know what the term "degree" is :-), and was confused. But seriously, your question is really easy , just as you said.更多精彩文章及讨论,请光临枫下论坛 rolia.net
                      • You answer has nothing to do with STL. By the way, if one day I tell you that I need the node of tree has a pointer to its parent, And move the node from memory to harddrive.what are you going to do?
                        Because your code is so versatile, I guess you must have good time make it happen.
                        • You just don't get how powerful template can be, do you? STL is just one example of template applications
                          本文发表在 rolia.net 枫下论坛I've backed my words by demonstrating my code and solving your problem : a tree which supoprts degree 4. That's enough. If you don't get it, that's your problem.
                          "the node of tree has a pointer to its parent"? And you asked " I guess you must have good time make it happen. "? Dude, you are funny. Yes, it must take the rest of my whole life to add one line code! LOL!!!
                          And "move the node from memory to harddrive"?
                          Regardless the details, say file I/O, or in fancy terms, serializing,
                          What do you want to prove?
                          Do you really understand what generic programming is for? It's not magic, it 's not for everything, can you find me where I've said anything remotely close to that please?
                          All I've been saying is that C++ template enables you to write one generic code for any given algorithm/data structure, regardless the type of elements in containers.
                          Whether you get my point or not, I'll have to end the discussion with you.
                          It has been pleasant talking to you. :-)更多精彩文章及讨论,请光临枫下论坛 rolia.net
                          • 摆脱你写中文算了,你的阅读能力有问题,我说的是数据结构在硬盘上,不是让你存盘.我现在写的一些代码,连文件系统都没有用,直接就操纵盘上数据块了,这个时候,又如何呢?
            • Have you ever heard of C++ template and generic programming?
            • If you prefer void * for different types of elements in your data structure, and cast it back/forth in your applications, then enjoy it! I enjoy one genric code with template and "template <typename T>"
              let alone the superiority of template compile-time strong type checking to the error prone C style run time pointer casting.
    • 软件开发的精髓:重用.
      • 看来新手还比很多老手懂行啊,哈哈
    • 没想到玩C++的弟兄这么多,我还以为除了Java就是.NET呢!当年玩了1年MFC觉得太复杂转向.NET了,都是候捷那小子惹的祸
      其实挺喜欢C++的,STL我基本系统的自学过。本人学东西习惯刨根问底,看到MFC那么多暴露在外的古怪代码,一时手痒就找了本候捷的《深入浅出MFC》来看。说实话,那本书确实是我目前见到过的最好的介绍MFC的书,但估计还是当时功力不行,没怎么读明白。看到BC++ Builder 把那些古怪代码全都包起来了,就改用BC++Builder,但是Borland的编译器不争气,经常跑出来莫名其妙的错误,很不稳定。一气之下,抛弃C++,转向.Net
    • can't input chinese these days. nice artitle. it all depends. are you trying to kill a chicken, or a cow. pick a wrong tool will make the work harder.
    • 这个才是水平,不是口水话。
    • 现在轮子是不能乱说得了。改叫不用重新发明轱辘好了
    • C++从刚出来就开始用到现在,惭愧从来没有听说过STL,也做了、领导做了不少系统。不用什么东西地球不会不转的。用有用的道理,不用有不用的道理。我觉得决定项目最重要的是人而不是什么先进武器,一个十年前的计算机软件系统分析员说。
      • 对一个项目来说,项目组取得共识是最重要的。妥协也是一门艺术。重新发明一个轮子相比之下就此要的多。看问题从下往上看强调技术,从上往下看强调调动人的积极性。角度不同可能就是为什么年年月月反复出现这类争论的原因。
      • 同时作为一个PM,首要考虑的是在适当的时间内资源情况下完成指定的项目。可维护性是第二考虑。这也许很难被“现代人”接受,但这是一个事实。连项目都不能完成绝对不是一个好的PM。
      • 觉得别人在谈技术吧,和PM是两回事。用C++不知道STL,只能算很初级的C++PROGRAMMER或 者很老的又不UPDATE自己知识的SR DESIGNER。
        • 如果STL和virtual function都没用过, 那就根本不算C++程序员了.
    • 各位大侠,不好意思,小的插一嘴,如何简单地实现个B+树啊?多谢了
      • google C++ B+ tree, you can find a lot. e.g.
        • 汗ing, 看不太懂。我是做不了这份很有前途的工作了。