Day1 Key Note - BjarneStroustrup - The Essence of C++


#1

观众互动环节没有听,观众声音太小。听不出来。 另外有一些话没听出来说了啥,欢迎校对。

gentleman please welcome Charles Torre

excellent. thanks for showing up it’s great to able to do goingnative again.

last year was awesome, wonderful to see all you people, all you programmable in the audience

there is people on-line, thanks to the channel9 team for streaming this live, very appreciate that. so you can ask questions on-line.

But we gona take questions from people on this rooms priority you came. That’s excellent.

We have a great 3 days for you.

today we gona say pretty much iso for day1 and day2. mainly focus on standard c++.

day3 we gonna ??? some windows some more vc++.

I’d like to introduce our key note speaker. so we want to have Bjarne Stroupstrup to appear. the creator of c++, he’s gonna teach us a little bit about the essences. thanks for come-ing !


OK, here. welcome, seams the mic working.

so, in the next couple of days, you are going to hear a lot about the latest and greatest in c++. you are going to hear a lot about advanced tech and new features.

and I decide that in the keynote, I couldn’t go too much into that.

so I’m going to try to do the opposite. I’m going to try and focus on what is the essence of c++ . what is it that’s been constant over the decades. and basically that is it what kept c++ alive and kicking.

of course I cann’t quite insist showing some new and nice stuff so the last 15min or so will be about something from c++14.

but basically I’ll talk about aims and constraints , and the development first. I’m trying to explain c++ in four slides. and then going to some details of resource management, oop , ge, what challenge ahead.

so, basically, that is what we want , out of a programming language that is aim among things for system programming.

We want type safety. That will be ideal, we can’t be perfect about that. with the need to deal close to the hardware. and with the seal inheritance . but it’s an idea , it’s something we aim to improve.

We want resource safety. that is not just memory. so i’m going to argue that we we really don’t want to leak anything. and “things” can be, things like locks and file handles, not just memory.

I’m going to talk about performance, because , well, that is important. if it isn’t important to you , that might be better language for you to do.

predictability is very important for very large component of the c++ world. er, dealing with hardware, dealing with things that has to be happen quickly or reliable or repeatedly .

and we can languages that can be taught. we want something that is no more complex than the needs to be for the tasks is doing.

and of course we want to be able to read what we are doing. -er, you can writ unreadable code in any language of course. - but, we want to be able to write some thing on a good day, that people say, “wow, this is realy nice and clean an clear.”

these are the aims we much better added today than we were 20 years ago, and will be actually much better next year when we get c++14

and , we want…

the primary concerns of mine, is system programming, embedded systems, resource constrain systems, and large systems.

that is … err…

so, strictly, the domain of high qualified professional programmers.

and it may very well means that if you have a tool for that, it’s good for a lot of other things. that was one of my surprises early on what … so many systems has a clue to it where what I mostly interest in is essential and then c++ is so general, that it well do the rest also.

so, c++ is expert friendly, definitely. and, the problem is , that’s not enough. if it is only expert friendly, that’s nothing for narcosis. // NOTE, narcosis = 初学者

we must involve the language that is a bit more friendly to narcosis, without give in an inch of / bytes and cycle for the experts, what they really needs is bytes an cycles.

so part of this is my answer to what is c++.

I … I …, I have my ideas that’s not necessary the same as anybody else is. there are probably a big board that what you header in most place is, that is I try to see the whole elephant, and I find in forums on the web and conferences as such, people play Blind Men and the Elephant , and they are absolutely certain that their part of the elephant is the whole beast. there are wrong.

so this is my summery of what c++ is of you have to do in one slide.

its a language that provides light weight abstraction facilities. and its key strength scenario is where you build software infrastructure, and where you have resource constraint applications.

it’s not an elephant that light weight, it’s the abstraction that you can build. that is anybody can build a really slow, big abstraction. but, building at point, or coordinate or complex number that you can afford in competition language that is building facilities like that, is hard. and that’s what c++'s strength is.

c++ is , er , developed come from two of the main lines of development of programming language. the lower line here, were basically exploit the hardware, start with assembler, went though BCPL and C , and C++ gets a lot of low level stuff from C.

you can see people there, that’s of course Dennis Ritchie, that’s David Wheeler, my thesis advisor and one of the ten people came to written the first compiler. he can also claim to have written the first program even running on a store program computer.

so this is … a … good thing , good, good long tradition exploit the hardware maximally.

on the other hand, the biggest improvement in programming languages ever, was done by Backus’ team in IBM. when they decide to improve productivity of programmers, by letting programmers write in a language that fit for humans instead of those load&store hardware close stuff.

so we got Fortran, and you could get, er, programs written in exactly your own language provide you are certain kinds of engineer or certain kinds of scientist. so that’s how we go Fortran.

and as soon as this idea was heard, everybody wanted their language from their particular domain. so the business people got Cobol, where you can say business like things, copy files, write to tap and things like that.

and and , , very soon , there is couple of hundreds of languages. it is a terrible mess. because, every language that was good at one thing. you speak one language of one subset of the computing community. and, so the brilliant ideal here, from Kristen Nygaard, was to generalize these thing. ok, if you have a concept, if you have an idea, in your head, on you blackboard or what ever, you should be able to put it into a language in general. so instead of building language around special purpose concept, you provide the facilities for building new things. they called it classes, and class heritage,

here comes the line of general purpose abstraction from the hardware, and I brow that, and got the initial c++. we’ve been developing that ever since. and that’s been a lot of development in the world course, but I’m talking about this line here.

so, what we need, is to be able to do things really well close to the hardware, as well as anybody, and provide general purpose abstraction so that we can actually get the concepts we need in our program as opposed to always talk about bits and bytes.

so, c++ is of course not perfect. anybody who claims to have a prefect language, is either sale man, nor fool, or both.

c++ doesn’t actually aim to do everything for everybody. there are things that are less interesting and thing that you just don’t need, say the efficiency, close to hardware, or you don’t need the abstraction. there are alternative things, we are not trying to be every thing for everybody.

you has a solid fundamental model, despite what you might have heard, or what your professors might have told you in class. that quite solid model for what c++ is not try to conventional about that, but basically has C’s model of the hardware and has a facilities for principle added new concept to a program.

and then this has been refined for 30+ years. that is “works”.

this also means, that it has a lot of “what’s” and it also means we know the “what’s”.

people very often shows something new, because, well, they haven’t learn it’s weakness yet, so it looks perfect.

we know the problems of c++, that’s partly an advantage, long term stability is a feature. that is in the despoil compatibility stuff, you find that, it is really nice that, my programs from ten years ago still runs. it is really nice because it’s sort of assures that our program will run in ten years again. we trying not to break old code, and performance we want to be a match for everything in usually we are. and this leads to a set of interesting applications for instance that are very widely used. it actually what c++ offers cleanly pays off for somebody, otherwise they wouldn’t be using it.

so i’m going to a little bit details. i’m going to try and get c++ down to just four slides. and the rest is details. if you understand int and vector, you understand c++, and are a lot of details. but don’t get lost in them. that’s the point.

btw, I’ve just written a new book, very thin, 180 of stuff plus an index, which claims to present all of c++ at certain level of detail. so, if you actually are an inexperienced programmer, here is what you can get an idea of c++. so, that’s the end of the advertising. for now.

er, so, what do we do.

the c++ first of all, we have to map things to hardware. the hardware is where programs run. they don’t run in mathematician abstractions. the run on hardware. basically the primitives operation are instructions of the machine.

we have value types (many of them) map directly to machine instructions, some don’t. but they are simple. they are values. if you understand integer , you understand about anything that is a values. you can copy an integer, you can do things to it. the other kinds are handles. they have handle to control access to data… values. so, here for instance, we have a vector that keeps track of how many elements that are, and give you a subscript operation and copy operation and things like that to manipulate the value. there is a lot of things like that. but those are two fundamental building blocks we’ve got. and we compose by simple concatenation. that’s what happens to an array if you put objects next to each together. and classes/structs you put each other with different dimension. but basically there is nothing more to it. there’re ways of composing these basic things. and when you look at your code. you can sort of think about what is in the memory and understand it . and when it comes to an primitive operation you can see which primitive operations are done.

then, to get away from this concrete low level view, we have classes. the most important part of a class is constructors and destructors.

we define ourself a new type. and when we initialize it with some value, that’s called construction, and when we finish, clean up the mess. so, if this is a resource handle, this will acquire resources and this will release it. so, basically there is a clue form about two leak insulate design in C++ classes long time ago. a constructor establishes the environment for the members to run in, and the destructor reverse its actions. it’s like a pair of pants phrase, but I haven’t invent the words constructor destructor yet.

but, that’s where a lot of c++ comes from. right there.

and … now … once we’ve got classes, eventually we get abstract classes and inheritance.

here’s the wey we define the interfaces that is complete insulate users from the implementation or visa versa. it has couple of virtual functions and a set of pure virtual functions. there is no data members so it’s not a brittle base classes.

you have to manipulate these from pointers or references unless this is essentially every body does. and that imply some overhead, and it apply some lifetime management that can be very messy if you don’t think it through. and you can build hierarchy base on that.

next, we have parametrized types and classes. using templates, that’s the essential support for generic programming. and secondly it allows compile-time computation. basically you can have a vector that’s parametrized by it’s element type; and have a sort function that’s parametrized by it’s container type. and so we can make a vector of doubles like that, an we can sort some vector with that. that’s the essences of generic programming as represented in c++.

there some things that are said it’s not c++. it said it’s not everything. some of these things that are really quite fundamental in the design of c++ for good and bad is that no crucial dependence on a garbage collector. a gc is centralize resources so that’s contention for it , in a machine . I remember the big old time machines, 64 processors ,real beast, what we do ? 63 of them are waiting for the gc c++ is designed not to have this problem. it has other problems in exchange. but this is fundamental issues. similarly there is not guarantee type safety. we did not want it for all constructs, we have C compatibility, we have history, there are needs to deal with hardware, requires us to break the type system. we like to minimize we like to encapsulated it. but it was a decision a long time ago that c++ runs on a real machine, it not a mathematician abstraction that it grounds on. and it no virtual machines, if you wanted to run on a virtual machine, you can, but something has to be run on the real hardware, for instance the implementation of a virtual machine. also there are many domains in which that you can not afford a virtual machine, and you can want to exploit the facilities of the hardware. if you running in a virtual machine, exploiting the GPU gets rather tricky. if you are on the machine itself , you can go to something that might be type unsafe, that might be an extension, but you can get there.

I have a feel, pictures on these slides, they temped us to do something with c++, so you can wonder what it is. that, that , there is a distributed computing system with wheels.

there are also things that are not c++ for reasons that are regrettable but they are market realities. there is no huge standard library, because we don’t have a owner, we don’t have a sugar dady that can produce free libraries to ensure market share.

we would like to fix that, sure herb would like to say something about it , yeah he’s got a big screen , it’s one of his favorite topic. and, we have no central authorities to approve or reject or help integration of the libraries. integration of libraries is very difficult. and we would like to do much better than this.

for the moment, these are the market realities, this is the way the world have been. for c++ all the time. so we have no standard GUI library. we have, maybe 25 competing frameworks which is just as bad as none. awfully again, it’s unfortunate. we don’t have all of these things yet standard, but they exist. you can pick them up, you can use them today. but they are non-standard. we would like to do better than that. I don’t know if you remember the dragon book, that the knight is slaying dragons in complicity like that.

well, some time the dragon wins.

so, well, going to start on slightly more kicking things. we’ll go look at resource management. basically we have things that we would like to control in system, like memory, the elements of vector, the characters of a string, the file handles that your operation system provides, threads, locks and things like that.

basically what we want to do is to have a handle that we used, to control access and make it convenient to use these things. basically , the standard way of using this, is to uses constructor and destructor. the constructor acquires the resource, yeah it’s memory because it’s a vector. and the destructor, well , gives the memory back again.

so it’s very simple. here we have a function, has a vector, it makes a vector, and at the end, when ever we leaves the function, how ever we leave, the destructor cleans up by releasing the memory again. basically idea is very simple, details can be quite heavy depend on the resource, depend on the constraints of the problems and as such.

but keep that picture in mind. and you can write a lot of good code. the handle usually is scoped. as long as the handle is in a scope, and not put on the free store, and the resource is held by a handle, clean up is automatic and simple. the resource is held for a minimal amount of time, name is scope in which was created. basically this is sort of the code here. what the constructor do, it acquire a resource, set the memory, initialize the memory needed to control things, and possibly does some initialization over what it has acquired. and the destructor reverse that. very simple.

so. a resource is anything you acquire and have to release. explicitly or implicitly. that’s my definition of resource. a resource should have a owner. I really dislike stuff that just flat around in the system. and well, people hope some body will take care of them. at some point. if there is an owner, the owner’s job is to make sure the life time is managed, it’s initialized up properly and cleaned up properly.

and the ultimate rule for resource is it’s scope handle. doesn’t have to be scoped, but it’s easier if you keep it scoped.

it is also know as Resource Acquisition Is Initialization. horrible morph. often reduced to RAII. I can say it’s a horrible morph because I invented it and I name it , I should have named it something better, but , well, hand side is relatively easy.

basically if you failed to acquire your resource, you throw an exception. it’s one of the fundamental reasons that exceptions are in c++. there has to be a way of getting out of a task that you have been ask to do, and can’t do, like constructor can’t construct its object. it has to be able to get out of there. if you don’t have exceptions you have to fake them. you try to construct an object, but the object is in a bad state. you have to test every bit of it, pretty horrible stuff.

basically the rules for not leaking becomes never throw by holding a resource that’s not own by a handle. if you do something silly, like acquire some memory, and hold an pointer to it. and throw exception, you’re are in deep trouble, we’ll get back to that.

ok, here is an example, we have a mutex, it’s a system resource, and we… sorry…

we have something we want to share, which is a shared data here. and we want it controlled by mutex. mutex is an standard system resource, and it it represented in the standard library by the mutex class.

and the mutex class is actually a handle to the system resource. and so … what … er … system resource… yeah just think about it is a system resource. going to a scope, will take a lock on it. that is the local object that hold the mutex. use the data, and we go out of there. we don’t care how we go out of there.

now this is of course the overly simplified … we don’t …

we often have more code working in that critical sections just there. we can goes out of there by return or by falling off the scope or by throwing an exception, but all of these cases, the lock guard will release the resource. that’s the main point. acquire use and release.

so , here is an example of what code I found when I look around, I found it is pretty awful. it’s not just written by java programmers, but it’s just getting more common that it used to be. there is always people writing code like the screen here. but unfortunately this is an increasingly problem.

so, I … get a gadget, get it on the free store, I learned OOP, every thing has to be on the free store, I manipulate it through pointers, so that’s what I’m doing. then I go down, I may throw an exception. and I , some one might say why exceptions are bad, because I may leak the gadget. No, I’m saying you did something else wrong. because you’ll get the same problem just from returning. in other words, i have this gadget here that i have acquired I have to delete it. and some how that puts major constraint on what I can write in the function. in particular, I mustn’t leave without deleting p;

and people then say the want the garbage collector. which you known. I didn’t say what is inside the gedgat. if that’s just memory, a garbage collector will help you. if it’s a file handle, a socket, and a lock, err… the garbage collector will not help you.

so this code is bad. if I throw here, I have leak the gadget, and gadget holds a lot of thing.

so, naked pointers are bad. because they are hard to manage.

so people say, let’s use a share pointer. a share pointer is one of these handles, they hold a pointer. when you acquire a pointer, It hold it. when you leave out of the scope, the share pointer will release the resource, if it io the last one, that hold it. in other words, a share pointer is a form of garbage collection. If i have a share pointer, I give you a copy, i give you a copy , the last one of us that gives up the copy , will destroy the object. that’s the idea of share pointer.

but you know, i’m not actually share anything with anybody here, that gedgat is mine on mine. and so, why am i dealing with garbage collection here? even the shared pointer version of garbage collection. if you people think I misused the word garbage collection, remember that original garbage collection is defined by share pointer, counted pointers. and because the language calles them self garbage collected, because every thing is a shared pointer. so, this is a form of garbage collection.

you know, that count for the gadget goes from 0 to 1 , and from 1 to 0 , which is what it does. I’m not sharing anything.
there is standard library unique pointer, that would allow me to say just hold on this one, and destroy it if i leave this scope;

that’s all , that’s unique pointer. don’t share with any body, that’s fine.

but, do you know? why am I dealing with pointers here?

actually the code I would like to become common and ?? , is actually like this. I made an gadget, what should the gadget be ? a gedget should be nice thing. if it hold some thing, it would be an handle to what it hold. if is a file handle, the constructor will initialize the file handle and the destructor will close the file again. if it has a lock, it will do locks on locks as needed, if owns a memory, it will acquire memory on construct and release the memory in destructor.

all of those automatic is gadget’s job to maintain the gadget’s resource. right ? I mean, i have an abstraction should be proper abstract, these should be no longer a problem. because the destructor for the gadget, will take care of it.

and some, things are simple. I really like it when you take some complicated code like that, and improve it by make it much more simpler. that’s the idea. we want to have simple things simple.

there are things can not do, with just RAII. there are complicated data structures that require more thought, there places that require share pointer etc, etc. but simple things should be simple. and this is am example of it.

so, what do we actually use pointers for? if i’m saying, pointers should not represent ownership. handles represent ownership, and pointers live inside handler, and used by them to reference resource by them. also, you reference resource inside a handle. you represent positions. that’s why we have pointers into a ?? like we use indexes. and we have iterators, all of these god stuff which are pointers in the sky. by and large, represent positions we have to be careful, we can have range checking.

they (pointers) are really good to pass in large amount of data around. usually in the form of reference and const reference. that’s how we, say , pass to matrix into functions. for matrices, we pass const references. pointers in the sky are really good thing to pass things to others.

people use pointers pass things out of functions. DON’T. and I’m going to show alternative to that.

we can get informations, representatives inside functions, we can get informations into functions, but how do we get it out again?

the idea of getting things out of a function, usually if it’s a lot of data, if it is a complicated object, we put it on the free store. the problem is, we use new to get things on free store, so who delete? is the operation that create the object? or the code that call the object. neither of those solutions are ideal. neither of those solutions are un-manageable. but a lot of the un-manageable resource management using a lot of pointers. has a root in these problems. people don’t decide who owns what and who cleans what. so things pass to an interface, and disappear.

we can try and solve by references. that’s even worse. because I return some reference to something that’s on the free store somebody still has to leak the pointer. and the obverse question is, what pointer? I don’t see any pointer. A reference looks – when used – use like an object. and you have disguise the problem rather that solve it.

we can pass target object. so instead of adding two matrices and returning a result, we can say add(a,b,c); it takes a + b and put the result to what ever c points to.

that a popular way of doing it. the problem is where it regress towards simply code. and output parameters is one of sources to complex and confusion. when I say plus(a,b,c), what does that mean?

I have to read the documentation. at least we have const, so that we can tell which one is suppose to be inputs and which one is not. but if people are not consistent and they just look at the code. what’s what ?

this is source of bugs.

similarly, the code before hand just looks like a becomes b + c , now looks declare some result type c, and plus a become b become c. that some time it doubles the amount of code you have to write.

I don’t like the solution, it works, some time it’s the best we can do. but we are regression. we throwing away few hundred years of progress in notation.

and we can return an object. we try that, that works nice. if the object we are returning is an integer, or complex number (NOTE: std::complex<>), that’s not a problem. if it is a matrix of a million elements, even a modern process can … can feel the pain. and so, copies can be expensive, and then we start eventing tricks for returning objects cheaply.

well, that sort of works in the hand of competence programmer in a code base strictly controlled by somebody knows well doing it works. but , in this area here, is where we found a lot of the awful code that, for not solving this problem permanence a million line code base and become sources of problems.

so, we can return a handle, that’s simple an cheep. don’t return the elements of the matrix, don’t return pointer to the elements. return the matrix which is the handle.

ok, so, how do we do this. here, this is what the way we want the code to work.

i want a matrix that takes two … (BS纠正口误)… plus operation that takes two inputs and produces the result. I want to do that by making up a local variable, I want to fill it up with the good stuff i want to get out. and I want to return it.

and I write my code like this. and … this , this works nicely.

in here, “r” is a handle to elements, and the return operation is simply - take that point there and give it “res”. and then put a nullptr in its place. that’s know as move operation.

even little kids can understand this. look, here is an object right, I moved it over here. it not here.

ok. only a computer scientist would make a copy, move the copy over here, and destroy the original.

You actually need a degree to figure that one out.

little kids at about 8 - 6 month can do this.

ok, that does it look like in code.

this is a funny notation, that this one is a move constructor. a move constructor is called from some thing that we don’t need any more. like the source of a return statement.

and it does exactly this as I said. here, it copies the representation and zeroes out the representation. now , it copies because that’s what hardware does well for small things like a pointer, or integer. and the matrix simply is just integer … it may be … a pointer … and it may be a pointer and a couple of dimensions – its small.

so, we … this operation here, the move operation is … is something that is really cheep. so if you want to move a million elements matrix out of an operation, it cost two DWORD assignment. that that’s affordable.

ok … so … errr.

this leads me to the conclusion that no garbage collection is needed for this simple implicit and efficient resource management. we can do that. and so , we had a set of techniques : fist we store data in containers. and they should reflect the fundamental abstraction in their interface. and they handle lifetime management. and you handle all resources with resource handle. not just memory. this is important. I don’t want to leak sockets. I don’t want to leak file handles, etc etc etc.

your system have a lot of resources. some of which I never heard of. they are just something in your system, has to be acquired and released. that’s resource, all of those have to be managed.

if you can’t get this working, you can start using smart pointers, unique pointers are very good at holding things to scopes, they are also very good at hold unique ownership, hand unique ownership over to somebody else. share pointers for the case is where you can’t work out the ownership, it is really uncertain who is the last user. try not to get there, but when you get there, smart pointers share pointers will do the job.

finally , if you have gotten yourself into a mess - which a lot of us has - especially with old code - lots of pointers, no real understanding of who owns what. no really clearly actual clearly set of rules for error handling and resource management. this is not uncommon. or if there is is some clearly apically rules that may not be followed, in that case, you can plug-in a garbage collector. and get what’s known litter collection.

their shouldn’t be much garbage for collection. because we already built with most of there. so it’s relatively cheep. c++11 specifics an interface for this. but it can still leak non memory resources. but i can be efficient and effective , and you can go if you want to. but the point is , the usual order of preference has be reverse here. it is not the idea is garbage collection, and if you don’t have garbage collection, we will do something else. no. the idea is perfect resource safety. with minimal overheads and minimal resource retention times , and then eventually if everything else fails , we can plug-in an garbage collector. at this point, garbage collection becomes cheep.

so, em… I sort of uncomfortable when I don’t show code for awhile. so let me show a little bit some of the facilities we had in c++11 with the general purpose of making simple things simple. so here, I want to find all v(s) in C . C is suppose to be a container. v suppose to be a value that might be in the container. how do I want to return that? I want to return that in vector of pointers to the elements in there.

I know that the pointer is.

so basically I’m gather in the addresses of all the elements had value v, in a container. that’s fine. what’s what I do.

then I implemented it by making a local variable, and I filled it up, i use the new for loop, the “range for” loop, and I said , for x(es) in C, and x is of course of the reference type of the elements in C, the compiler knows that so I don’t have to tell it, that’s what “auto” says, and its reference, because I want to collect information of where they were. if X equals v, push its pointer to it onto “res”, when we finish, we return res.

so this is like the matrix example, basically I just make a collection of things and I pass it by value, return it by value. and vector, in c++11, vector it has move constructor. so this is actually very efficient code. don’t try this on c++98. because it will be a performance budget. but all the rest here, you can write c++11 so you are saved from that problem.

and we use it (NOTE: the function find_all), take a string. a string is container of characters. right. and then I say … err. for all p(s) in the result of find_all , so I just going through the vector, which happens to be a vector of pointers, and if it doesn’t points to an ‘a’, we have something serious here. because I’m saying the ‘a’, and so it’s a bug. string related. it’s a bug in string and it’s a bug in find_all or something like that.

this should never happen.

so, this is fairly simple and uses a fair number of new features just to wake those of you who hasn’t seen this before. let me just point out, that “auto” is the oldest c++11 feature, I implemented in 1983 or 1984, and I was forced to take it out for compatibility reasons.

but it actually notationly very nice thing. I don’t have to remember what the return type of find_all is. and what is the value type of the container that came in some where. the compiler knows, so I don’t have to tell it.

for generic code, that’s really nice.

so basically, what I’ve been saying here about resource management and move semantics, is deep inside the standard, all the standard containers are handles, vector list forward_list etc etc , all the standard resources like threads, locks, files and unique pointers , use this kinds of strategy .

you don’t have to start from scratch writing this kinds of stuff, it’s already in the standard library. and you are probably already using it. if you are sorting in a vector, you’ve already using something like the move.

ok, now. no no presentation of sort of essences of c++ could failed to mentioning object oriented programming. but you know, these days, I found, just about everybody knows most of what I going to say, so I’m going to keep it very brief.

c++ has a protection model, for this, you have public, protected and private stuff. I like stuff to be private, because that limits the member or piece of code , the number of programmer that can messed it up if you have to use protected.

there is no universal base class, because I consider I universal base class an implementation oriented artifact. there is simple nothing that is common to all types in terms of representation or interface. If you say that it has to be, you are imposing time and space overhead that might be right for a limited domain. stuff maybe very useful but it’s not fundamental.

and universal base class easily get to become overly general, because that is really where you put many things that are common for everything, and so you get more and more, and get hard and harder to maintain.

there is multiple inheritance. this is considered contravention places . but everybody who has static type in any form, has multiple inheritance of interfaces. so I consider that non-controversial.

and … so abstract classes provide most stable interfaces, and the best separation between users and implementers. we need multiple inheritance for that. some times it’s also useful for data. there are some minimal runtime type identification.

so basically, you use inheritance when the domain concepts are heritable. so basically, you have to think not in terms of programming languages about whether to use inheritance, you have to think in terms of the problem you try to solve, the information you’re trying to represent.

if you have an general hierarchical system, my usual example and the oldest one is the vehicle, trunk is a kind of car and … kind of vehicle. use it, and it’s very powerful.

however, it has been seriously over used. that people will think, building an deep hierarchy , equals a good programming.

NO!

if your domain is a deep hierarchy, representing it with inheritance is just right. if your domain is a shallow hierarchy, maybe what you need is what looks like, just an interface to implementations.

and maybe there is not inheritance necessary, in which case you don’t need a virtual function you don’t need hierarchy. don’t over do it , think before you you make a member.

so~~~ lets get to generic programming. this is the area that has seen most progress evolution over the many years. there’s something to say here.

basically in 1980, I wrote the first paper on C with classes. the first paper on here.

it has an vector in it, it was parametrized with element type, there are statements there, and the macro will do the job.

I was wrong about that. always wrong about that.
on the other hand, I had right problem. I want generic programming, I wanted , my vector, to be parametrized on the element type, not the sort function, to work independently which element type it was.

in 1987 , I wrote the aims and design templates it has to be extremely general and flexible . if it only can do what I imagine, that’s something wrong. because my imagination is not equal to the needs of even a room of people like this. let along all the programmers at all.

there has to be zero overhead. the reason was, that my least favorite data type in c and c++ is the array. and the array in C , is a data type so stupid it doesn’t even know how many elements it got. that’s a source for a lot of problems. it also converts in strange ways, it it it’s problematic.

so i would like to have a vector or matrix that would be a useful replacement for arrays in most cases. and , the C part of the c++ community are upset to the performance, so basic the “zero overhead” comes in here, not a byte , not a cycle . so, we have to be able to do that.

you have to remember that most people will think about abstraction, and generic code. thinks about indirect function calls. you can’t go through a jump table and still have performance comparable with manipulating arrays.

imagination if you are operation for sort scripting or you are operation for going two elements over in an arrays, was a virtual function call. you’re dying in the world for compare to arrays, and the arrays will live forever.

and also of course I want well specified interfaces like everybody else. I knew that well specified interface is the foundation for a lot of good architecture stuff. i was the one who put function argument checking and conversion into c++, what later and C because function prototypes and such. it’s one of the first things I did. I knew the value of that.

on the other hand you know, I didn’t make it.

two out of three ain’t bad. got the first two.

but the third , failed miserably. it has kept me concerned/worried and working on it for 20 years.

I’m going to finish this talk. showing where the current state of that work is, but basically I don’t think I had a choice back in 1983. I don’t think anybody knew how to get 3 simultaneously.

and if you have to pick only two, well, I made my choice. therefore for c++, probably might be the right thing .

so, what we have from templates ? they do compile time duck typing.

basically, they expand the code, and they check the expand code. nd that leads to template meta programming. it leads to very good weaving of information from different sources. but it also means, that an error is found in the generated code, in the extensionated code and most of you while you seen these error messages, you can get out of that.

I used to think of that, sooner or later, the compiler writers will get smart enough to write decent error messages. but I was … well, it hasn’t happened. I still get error messages that doesn’t fit on my linux window, they scroll off the top of the window and I never see the top one. things like that. we need to do something about that.

but, let’s see. template is a massive success in (c++)98, it was better on later c++11, and it will be better in c++14.

basically we have containers, we have algorithms, they are in standard library organized as STL. which stands for STL(NOTE, Bjarne would have said Standard Template Library). and … errr, there is(will be) much more.

I need better support for compile time programming because template meta programming gets too complicated often, constexpr provides a facility in c++11, just generalize const expression, basically you can define functions that are to be evaluated at compile time. you can force compile time evaluation in-places, and you can do const expression evaluation at compile time for user defined types. provided user defined types are simple enough know as literal types. I know some of the talks there will get into some of that.

OK, we are making progress.

basically what we have now, and what we looking for, is algorithms. we must get away from writing all our code from scratch in the basic language. we need to raise our level of abstraction to the point , well, instead of everybody everything been just integer adds and subtracts ,and things like that. we say, we use these algorithms, like our catalog algorithms. and here’s sort of classic examples , we sort a vector, and we find an element in a vector. the STL works on sequences of things, so we have to have the beginning and the end. but basically this is parametrized, it is generic or the kind of container we are dealing , here is a vector, here is a list, it’s generic over the elements of those containers. there is, let me think about it, over a hundred algorithms now that’s standardized , and I 'll hope you’ll writing your own and add to it(the standard). and we don’t think too much of that as we should.

basically, we want simple and efficient and general implementations.

here we got find, if you like C syntax, it is beautiful, if you don’t , that’s what you’ve got anyway.

and also we want to parametrized with operations. that is, we parametrized over the container. we parametrized over the element type, and we parametrized over the actions to be taken. here is the predicate passed to find_if, I want to find anything that meets predicate less_than{“Griffin”},

so we generalized find_if that was shown before, if simply uses the predicate, “while we haven’t reaches the end , we didn’t find predicate and then goes to next one and try again.” if the point you finish, you return.

ok, there is spin in c++ various ways since late 80s, early 90s. so we write a lot of function object, that’s the way we represent operations, predicates, etc. they can carry states, that’s important. there are easily inlined , they actually work better in simple cases than an indirect function call. and so here, less_than ( strings) that suppose to take a string you’ll compare it to , and then compare when you ask it. and that’s how it was done.

here, take the “Griffin” that’s what I want to compare to, and whenever I want to compare, it calls the object.

if you get tired to write these function objects, we can use lambda instead. which is basically a notation that says, give me a function object and use it right here.

so here, I want to , to , to do the find_all, and I want to compare to the value “Griffin”, done.

if you get tired of writing all these begins, you don’t have to, you can simply define your own versions that works over a container. it’s not perfectly as general as using pairs of iterators, it is notationally much nicer. so here is find_if.

find_if in the container c, that looks … odd.

ok. err…

back to the problem of specifying interfaces. I find that duck typing is in-sufficient,it gives all of those bad messages in addiction to what ever the good it does.

it leaves error detection too late, and it gives compiler writers too hard job. because there are no proper interfaces. these is no way else says, this is what the algorithms requires over the argument. this is not sit some where , there is no way for us to say it in c++11. that also encourage people to look at the implementation details, because they will look at them anyway. there is no interface that protected them from the details. and that means, every time you change the implementation of an algorithm, some user might be affected in an surprising way, so that users interest what’s inside those abstractions. they are no data abstract.

that leads to people start generalize their implementations so that users ,so that they have a great user base. this gets to a mass some times. and further more it doesn’t integrate too well with other parts of the language. you have to teach this kinds of coding in a different way than other kinds of coding. and you have to to to to think about in a different way. that’s not good. we are not good at keeping one style here, and one style there. it should be better integrated.

so, I think we have to rethink generic code, so that it become similar to the way we think about other code. so we need interfaces to get better error messages, better specification of our algorithms.

so, here is what I like.

here is some traditional code, we have a square root of double, we return to double, we have a double, we call the square root of double with the double, every thing is fine.

that’s what we learned in some versions of our long day one of programming class.

and if we give something to square root that isn’t a double, in this case, a pointer to double, we get an error . that compile time right there, simple, straight forward. we all understood that. very simply. now I want to see the same thing with generic code.

here is a sort, that sorts containers. here’s a container.

fine … we sort the container.

here, when it’s time to sort something that’s not a container. in this case is a pointer of a container. and we should get an error right here, and it should be comprehensive. so I would like to see a generic programming that’s very similar to ordinary programming.

so, this is what we have working with. something called concepts lite. it is also known as constraints, but after people have talking about concepts for a decade, in variably they became concepts.

but since they bundle less than 1/10 of the complexity of the old c++0x concepts, it became concept lite. sorry to Coca-Cola what ever.

basically we try to answer the question how doe we specify requirements on template argument, we want to state the intent and we want point-of-use checking. so basically we are provide set of functions that states what we are requiring of an algorithm. so if i have an algorithm for sorts, it will ask for an container. if i had an algorithm that take square root, it ask for a double of positive number.

this is voted as c++14 technical report. technical specification , I believe it’s the technical term. I designed by me, Gonçalo dos Reis and Andrew Sutton. Andrew Sutton has the basic implementation of all the basic stuff and most of the details . basically for those of you who have lift through the c++0x concepts, there are not concept maps, there are no new syntax, and there are no scope and look up issues.
the specification is very much simpler.

so, the first thing we have to ask ourself when working on those, what are concepts? and one of the notions that we came up with what is concepts are fundamental. people were writing specifications that were very very detail in theory. there literally was 120 concepts in c++ standard library. and look at it, how many concepts are there in the algebra ? a dozen ? is c++ standard library 10 times complicated as algebra? I hope not. it certainly does not have 10 time as many fundamental concepts. so we have to concentrate on building concepts in a language as what you have that a fundamental application area.

you has to remember that concept comes to classes that describes that area, you don’t have a free choice really. if you are dealing with arithmetic, you can’t define what it means to subtract, independently what it means to define addition. you can not define multiplication independently of the first two. these things hang together.

is not just syntax, subtractable is not a concept, it’s something you can say, but it doesn’t make any sense except in the context of something that’s specified , say arithmetic.

and we always have concepts. notice that, C have concepts. integer, arithmetic , they are just words in the standard, just like c++ forward iterator, and predicate. just words, in the standard. we want to make it real into code.

so, basically we are looking for some thing fundamental. don’t expect to find something fundamental every year.

I don’t expect to once we got a body of concept to describe things, I don’t expect to fond one every year.

it is not the minimal requirements for an implementation. if every algorithm is specified as minimal requirement for it’s implementation. we have a problem.

if we want to improve the implementation we have to change the interface. that’s bridle.

what we need to do, is specify interfaces in terms of general concepts, so that we can improve the implementations without affecting the users, we also want to have so few concepts that we actually have a chance of remembering them.

I couldn’t remember that sole of concepts in c++0x. I do expect to be able to remember the concepts in c++14, or 17, what ever. because there will be few hands of them.

Andrew Sutton and me , work on something and we got the STL down to 16 concepts. I believe current version is that thing.

A concept is a predicate on one or more arguments.

we say that T suppose to be a sequence, simply at compile time, we check whether T is a sequence. some where, there’s definition of what is it that meets sequence, has an begin an end , for instance, and we just ask if T meets that. if it’s a sequence, answer is true, if it’s not, answer is false. we can do that on compile time. we have constexpr functions we have functions that can be evaluated at compile time. and we can write things like that.

this is by the way , describe running code, you can download a branch of gcc and try it today. this is not science fiction.

template declaration will look bit like, you can write like this,

here we have find, basically we have need a sequence S, and we need something for the value type of sequence S can compare equal to that of value type T. and so it takes a sequence and a value of that type. and now we can write code like that.

it looks exactly as it used to. the only difference is, we specified find , precisely , so that all the information for checking is available at the point here. so lets see what happens.

here, we have sortable concept some where, and takes a container. we take one container which is a vector, one container which is a list. and we sort the vector. ok, the vector is sortable. sortable ask for things like random iterator, you can do subscripting like that, every thing is fine. sort a list, will fail – because list is not actually sortable. they don’t have the necessary stuff to poke in different parts of an object. the best way to sort list is tern to be copy it to a vector, sort and copy it back again. but that’s beyond … it not on here. – instead, it gives us an error .

so here is actual error message from this code. list does not satisfy the constraint ‘sortable’. and if you hit, oh . ( in response to applause ) Thank You.

by the way, if you hit another compile option, it will tell you why list is not sortable. it will come back and tell you … that it couldn’t … it it it doesn’t know where the scrap ???

but that’s … that’s … en… I like the short version and who likes the longer version.

the shorthand notation is if you don’t want to write all of these require stuff, you come upset you can actually write, we need a sequence S, for which the value type of the sequence is equality comparable to the other template argument T. and we can say iterator T find … well. some people like this notations some people like the others.

you have a choice. (和前面说 template syntax 没有选择呼应了。)

this is just the shorthand. it expand to the required version.

and we can handle essentially all of the Palo Alto technical report. Palo Alto technical report is a hundred sum page of document specify every algorithm in the STL and this was done by a group of about twenty people in parallel in two years ago. Jon (Jon Kalb) was there, I was there. it was called by Andrew Lumsdaine from Indiana (University ), which is one of the main workers of c++0x concept. and got Alex Stepanov, who is the father of STL , to chair it, and we spend a week, simple specify everything.

so, first, you figure out what you want, and then you figure out how design a language which will do it. that’s the right way around ( PS: 他在说 java/go/c# 这种领导拍屁股想出来的语言么?)

don’t go and look for fancy language features and see how can can use them. this idea, that you look for problems that fit your tool is wrong. so we did the other way around. all of the work on concept lite is done on applications and find how we can support it. and we don’t have the semantic parts, because , we consider that … would be too much to handle just now. we don’t see problems that checking template(definition) in isolation but we don’t do it. that is, we check the use of a template , if a template specify to require something, we assume that the implementation will stick to that contract. we don’t actually verify it. we think it can be verified bu you have to be very careful.

those of you who has … words with strict functional languages like haskell, we know it’s really hard to debug, because you made slight change to the implementation, like insert the extern model printf, the interface change, and every thing has to change. that is painful.

we didn’t want to go that, we need more word experience before we standardized something like that. and we actual use require that much.

overloading is fairly easy. we have two versions of find, one for sequences and one for associative container. if I take a vector or multiset, I try to find something in the vector, it will find the first overload and go and search along. for the second one, it will notice that multiset is an associative container, it will pick the second one , and it will do the search in the associative container, which is certainly not a liner search through it. that works.

and if you look at it, the overloading is based on predicates. that means, we don’t have a notion of a hierarchy refinement thing. we simply take the predicates, flap them out as boolean expression, see which boolean expression is subset of t other. if it does, we have refinement relation. if not , we just see what works. if it calls one function and not the other, that’s fine. if it calls, it can call two, we pick the more specialized one, if we can call two, an they are not specialization of each other, it’s an ambiguity error . that’s the whole set or rules.

it’s just, do event diagram, that ont that ont and that one , finished.

so we compute what the ambiguity resolution it suppose to be, and the classic example here. we take advance. here is advance that take an input iterator, here is advance that take a bidirectional iterator, and here is advance that take a random access iterator,

the are implemented differently. and we are quite capable of piking the right one in all cases.

ok, how did we define it? well that just bool expression so you write bool expressions, bool expressions get tedious so you write functions that are return booleans, this all work in.

to help you write, there is “required(expression)” that takes a expression, if it is valid expression then return true, if not, it just return false. this will suppose to be implementation details, but everybody scream, they want it, so this not part of the technical specification.

and to recognize them syntactically, I will show you why we need to do that, we call them concept rather than constexpr. we simply take the work constexpr out, and put concept in. so that they are the same thing except for the syntax analyzer.

how do we get to sort a container? basically, it’s a terse notation what I call it. it means, sorting a container means sorting a type that meets the container requirements. and that again means give me a type, check the containers requirements on it, and use that type as argument.

so basically these three ?? I use the underscore underscore to show that it’s actually not a … it’a generated name that you can’t actually refer to. but this is equivalent.

so if you like to write out the longhand yourself, you will write something like this.

it will assert that it’s a container. and we do the stuff. so, this is part of this idea of making simple things simple.

this is the simplest algorithms work really nicely for this ?? . and it looks just like our traditional functions. so sort , sorts, no … sorry, square root, take a square root (sqrt) of something that can behave like a double. and include integers. basically it equals ( think of the sort function … no no no ) (that) the square root function has been specified with the predicate that it’s argument has be able to behave like a double.

so, we do the same thing more general, with sort, it requires something that can behave like a container. and we have these predicate for testing it.

now we back to where I want it to be. here sqrt doubles, this works, it doesn’t. sort containers , this works, and this doesn’t and we get one liner message there.

so, we can start thinking about generic function exactly like other functions, and you know they look like other functions.

now going form the simplest cases to the the more complicated one. lets see that this actually how well handle the complicated one here.

here is merge.

it’s a … yeah, it’s merge, right there.

it’s pretty ugly. it has given many people headaches, including me. if you think that’s too easy, try accumulate(). it’s even worse.

so we need to get this stuff under control. we look that’s just too ugly , too easy to make mistakes, too repetitive , ah, not good enough. so let’s try simplify it a bit.

we can say forward iterator for , forward iterator as the shorthand, and we use one requires that predicates these three and check the connections between them. for complicated algorithm that take many arguments, very often you have predicates that takes all of these arguments and works some relation between them. it’s a matter fact, i don’t think you’ll have a good algorithm where there was no relationship at all. at least it’s rare and these domain.

and so, this is quite readable, and we are try to attack this problem. if that’s your solution, we know what your problem is. you have to simplify. we can simplify even further.

I just said we had a concept that test that three types for mergeable. so we have a little notation using ??? it says, give me three types that meet this. and here are the way i’m using these three types.

we just rap the whole thing up and just say, give me a set of types, that meets my requirements.

so that introduce three names in a scope , " For For2 and Out" which will using here. and it says that once you give me that in a call, I’ll execute the predicate “mergeable” on them to see whether it works.

and, that’s the way it looks.

obviously, we take three type names, the first one have to be forward iterator, the second one have to be forward iterator too, not necessary the same forward iterator type. and then we have output iterator, we have assignable requirements and comparable requirements. that’s it! just the predicate.

so, this sounds very good. we are of course not finished. that is, there are mush more we can do to improve c++. so let me finish off by looking a bit on the challenges that’s facing us. there are many and complicated.

those of you who are to take an Ancient Greek knows this is one of the labors Hercules(Heracles).

he is trying to kill a hydra.

very hard task.

so, c++ challenges. so, we want to make a better languages , and we also want to convince programmers that the new stuff actually works well.

and that’s relatively easy for actually getting people to use in large code bases. but. we first have to improve the languages and then we have convince people that use worth well.

and then we can start seeing the partials of introducing the existing code bases that doesn’t have it.

i refer to that as source code rejuvenation, and I think that is going to be an important issue.
so basically, what ever we do to the language, what ever we do to change the implementation, we can’t eliminate the c++ major strength. introduce to the language

that is a lot of people has a solutions that ends up been worse that the problem for a large number of people.

compatibility is a feature in itself. that means that ugly things will not go away even when you provide good alternatives. we just have to get people to use the good alternatives where they can. so compatibility is necessary.

performance, uncompromising , portability where appropriate , and we would like to increase, not restrict, the application areas.

if we could restrict the application ranges, we could be get a ??? language. but , actually there is a crew by me from about 1984, then even I can decide a ??? language.

that just wasn’t the exercise. it was not the aim of those that use by most useful language for more people for more application areas.

and I think that is very well worth pursuing.

so the challenge is I would like to close more type loopholes, we need to address concurrent programming, we need some thing that’s higher level that the threads, locks style programming which is universal necessary, and about the worse way writing concurrency system that I know of. we need to build libraries that provide higher model. we want to simply generic programming, I’m looking at concepts, we should … I means some of us have them today, but we need have them all next year. and we want to simply programming using class hierarchies, I’ve been doing some work on … multiple methods and functional style. em, some of it is available on my homepage, on the publications, and software also available. but it’s the research work, but I hope some of it gets into the language if not now then later.

you have to think in-long-term in this kinds of stuff. some times, you have to sort of imagine what the world would like in ten years, and try to get there. I suppose to thinking , oh ,dear, it will take more than a year, I can’t do it. the next quarter is essential … on that kind of thing. we have to have some longer term thinking.

let’s see. better support for … object oriented generic programming … get back to that. but I don’t like the way the community some time fold into different and waring camps when they don’t have an need to.

we have to support, combinations of programming styles. we have to make exception usable for real time project. one of the things I’ve said about is that exceptions are not used for hard real time, it can be used for soft real time. and the reason is very simple. it is, we don’t have choise that allow us to estimate how long it takes to recover from an error when exception is thrown. the tools don’t exist. I want to build it from 5 years ago but somehow I never get around to it. been an university students . it became too difficult just because it all to be solved.

it has to be publishable teachable and fashionable .

but we need to make exceptions more usable. and we have to deal with multiple address spaces eventually.

the notion that everything works in a single address space is … it’s creaking , it’s difficult. we get these big memories with lots of cores lots of things, but they are uniform any more. different memories takes different time to use in such way. I think we need to think about that. access. we want more domain specific libraries, and we want to develop a better specification of c++. I think English text is… err, is , maxing out in terms of what we can handle.

finally I just do a little rant. I really dislike the word paradigms. it was invented by coon and imply some superiority of one paradigms over another. and thins changes, everything changes, nor the older stuff became bad.

Kristen Nygaard said, you know, addiction didn’t actually become useless just because we invented multiplication, nothing was over turned, you incorporate the old stuff, maybe you have to re-phrase the old stuff. newton mechanism just not disappear just because of Einstein, it became special case, actually a very useful special case. similarly, I would like to see OOP, GE, and conventional programming just as differential aspects that you can use in combinations and I want be able to develop rules for how you do things that doesn’t chock in terms of these paradigms which might become semi religions.

and the focus has become language features , do I write templates do I write virtual functions, that incomplete senses. so I think it makes harms, it makes things complicated, it grades bad code and people write code for instance, they believe object oriented is right, they are write generic code, use interfaces in virtual functions, which is less convince than templates and long much ??

and similarly you can have people that so believing in generic programming that they make everything into statically resolved overloading and they should have build hierarchy and dynamic solution will much simple and easier to debug and document.

so here is an example of what I mean.

I want to draw all elements in a container. And I want that container to have value type that is the type of the element to be pointers to shapes. fine, and then I want to for each elements in the container, I want to call draw.

now, this is the generalization of the classical object oriented programming draw all shapes. that was first on… way back in 67… for useful paradigm. before they have screens that could do this kinds of things. so this is an old program. it’s obviously object oriented code. also see here, it’s clearly hierarchy of shapes. and there’s a virtual function that dispatches to the right kinds of shape. this is object oriented code. obviously it’s generic, look , it is parametrized on the kinds of container and you want to do the same to … element type …to that … and you call for_each algorithm. cleanly cleanly it’s generic programming. but it’s also very ordinary programming, I just want to draw everything in a container. and I just call a couple of functions on them. it happens to be a lambda, but … hey, it’s just a peace of code that called.

so, I don’t believe that you can creditably claim that this one is one and not the other two. it’s all three and integrate rather nicely, we have to work on this integration.

ok, we reach the Q&A time, and … I’m not sure… do we have some microphones that people can use? because I barely see people in the back, I certainly can’t hear you out there.

so any questions?

this one up there. ah.


#4

视频地址 http://channel9.msdn.com/Events/GoingNative/2013/Opening-Keynote-Bjarne-Stroustrup


#5

非常不错的文章,花了2个小时才看完,感谢楼主!