How to Deal with Multiple Return Values in C++

  Рет қаралды 211,260

The Cherno

The Cherno

Күн бұрын

Пікірлер: 249
@TheCherno
@TheCherno 7 жыл бұрын
Hope you guys enjoyed the video! Just some quick notes: the code I wrote at around 10:30 needs some changes to actually work, since we've changed the type to a std::vector. Specifically, you could write either std::vector results(2); results[0] = vs; results[1] = fs; or just std::vector results; results.push_back(vs); results.push_back(fs); but leaving it as I left it wouldn't work, since we'd be writing to an index outside the array. Obviously in the video I'm just trying to get the point across about using an std::vector and not really trying to write complete working code, but just in case I thought I'd leave this comment.
@platin2148
@platin2148 7 жыл бұрын
TheChernoProject In newer versions of C++ we would use emplace_back not push_back as the second creates unnecessary copys.
@xxyxxyz5322
@xxyxxyz5322 7 жыл бұрын
Just for completions sake. For std::tuple you can return the value like a struct as well: return { vs, fs }; And with C++17 there is the option of structured bindings for tuples: const auto& [vs, fs] = ParseShader("res/shaders/Basic.shader"); std::cout
@TheCherno
@TheCherno 7 жыл бұрын
In this case it doesn't matter if you use emplace_back or push_back since the string has already been created. You can check out my video on this for more details: kzbin.info/www/bejne/fpSohKitotF7e7s
@neelimgoswami6336
@neelimgoswami6336 6 жыл бұрын
really??
@ChrispyChris3
@ChrispyChris3 3 жыл бұрын
Just wanted to stop by and say thanks. I realized I watch a bunch of your stuff and need to start saying thanks more often!
@alguienmasraro915
@alguienmasraro915 3 жыл бұрын
For anyone reading recently, there's a better way with structured binding since c++17: Return a tuple of your choice and return it as per the video: std::tuple getData() { return { "One", "two", 3 }; } Retrieve values using structured binding: auto [str1, str2, number] = getData();
@hendrixgryspeerdt2085
@hendrixgryspeerdt2085 2 жыл бұрын
Much nicer, thank you
@slayer5171
@slayer5171 2 жыл бұрын
Why not use a class?
@antoniogarest7516
@antoniogarest7516 2 жыл бұрын
That's a nice syntax 👌
@pixelverdicts
@pixelverdicts 2 жыл бұрын
This is actually better than struct actually because with structs there are some issues with initialization and you need to maintain few things in certain scenarios. For example, try reading a csv file with header and try to put them in a struct so that they have different types for each of the column. structs are horrible to deal with.
@andrefaustino5514
@andrefaustino5514 2 жыл бұрын
@@slayer5171 Structs are simpler by a syntax pov. Class has some extra features that's not necessary here (constructors, etc...). Comparing if this solution, you have a cleaner code since you are removing a struct that's only used as a method response. I'm not sure about this, but I think you have a gain (not much I guess) in performance since you don't have to instantiate the struct itself. At the end of the day, I think it's only a syntax alternative.
@panagiotispetridis7961
@panagiotispetridis7961 7 жыл бұрын
at 13:20 It's worth noting that there are 2 more ways to make the code look somewhat better: In C++11 you can use something like: std::string vs, fs; tie(vs,fs) = ParseShader("directory...") // tie() is in the header And in C++17 you can even do: auto [vs, fs] = ParseShader("directory...") also instead of creating 2 strings at the end you can just return make_pair(vs, fs); or in C++17 return {vs, fs};
Жыл бұрын
Well, auto [vs, fs] = ParseShader("directory...") syntax not sound like a C++ at all. Adding a nail here and there just makes this already complicated language more complicated. ... C++ committee should just leave C++ alone 🥲
@nighma
@nighma 7 жыл бұрын
I think it will useful to keep these "optimization" parts in your video in the context you explain as a bonus for those (like you) who love it and try to create good optimized code. May be put them at the end of the video or display a little "sign" on the screen whe you speak about optimization if someone's complaining he's lost.
@p76yu78yu
@p76yu78yu 6 жыл бұрын
+1 to this!
@k-tech2937
@k-tech2937 3 жыл бұрын
Tbh, if one actually writes a c++ program, then one should ALWAYS optimize. Why else would one go to such lengths as learning a huge multi leveled language like c++ instead of using for example c#? And for me personally that is actually the part of c++ which I love most.
@MuhZubairAli
@MuhZubairAli 3 жыл бұрын
totally agree with you bro..
@slayer5171
@slayer5171 2 жыл бұрын
@@k-tech2937 I agree with you, Why use C++ when you don't want optimization.
@Djzaamir
@Djzaamir 7 жыл бұрын
i think structs and pass by reference methods are the best
@drewfyre7693
@drewfyre7693 7 жыл бұрын
I agree with you. I think for something with 2 return values I would use pass by reference but anything more than 2 I would probably make struct.
@antiHUMANDesigns
@antiHUMANDesigns 7 жыл бұрын
Structs are obviously the best, but it can get a bit cluttered, so it should only be done if it's gonig to be used a number of times. Can't keep making new structs for every single thing. However, structured bindings are decent, aswell, even though it seems this video skipped over that...? At least, if you're doing this for member functions, you can declare the struct a member of the class, to avoid cluttering the namespaces. In such case, structs are definitely the best, no competition. It really is a shame that you can't declare the struct inside the function, and use the function name as a namespace...! That would be awesome.
@antiHUMANDesigns
@antiHUMANDesigns 7 жыл бұрын
Actually, there's a way to do what I was talking about, using "auto" type deduction...
@NotMarkKnopfler
@NotMarkKnopfler 6 жыл бұрын
What if you’re dealing with recursion?
@Xx_McJasper_xX
@Xx_McJasper_xX 3 жыл бұрын
That’s what I do too.
@leixun
@leixun 4 жыл бұрын
*My takeaways:* 1. Tuples 10:49 2. Pair 14:00 3. Struct 14:30
@r17v1
@r17v1 5 жыл бұрын
for tuple you can easily extract value like auto [vertexSource, fragmentSource]=func() in c++ 17
@JackPunter2012
@JackPunter2012 6 жыл бұрын
I personally quite like 's std::tie function, not sure what that is like for performance but is a good way to have 2 named return types (of any type) without having go and write a struct for every function that requires multiple return types.
@RespecWamen
@RespecWamen 6 жыл бұрын
I'm really glad you use the struct way. I'm a newcomer to c++, i used to program in Java and I solved this problem by making classes with just what variables i needed to return. I'm happy now
@DrAuraHxC
@DrAuraHxC 7 жыл бұрын
I just want to say : C++17 Structured Bindings \o/
@k-tech2937
@k-tech2937 3 жыл бұрын
Cries in ue4 c++, cause no such elegant thing is available for ue4s internal data types
@simond3843
@simond3843 3 жыл бұрын
Thank you so much for your indepth coverage of coding styles. As someone new to code you are making understanding c++ a very enjoyable experience. Great Job Cherno!
@homomorphic
@homomorphic 4 жыл бұрын
I return std::optional with a struct. Typically you need to be able to return a valid structure or "nothing" and std::optional facilitates that.
@tehLyrex
@tehLyrex 7 жыл бұрын
I guess structured bindings take away most of the readability-concerns at least on the caller-side. Returning something like a pointer to an array seems very odd to me and creates very bad habbits. That kind of usage can introduce very serious bugs, especially with inexperienced people. That's a thing I'd never recommend doing.
@Dar1gaaz
@Dar1gaaz 7 жыл бұрын
well actually you can use brace initializers to initialize a returned pair just as well as you would for those aggregate classes. But I do agree with you on the clarity part. Used to like std::pair, and for some part in the stl there is no way around it, but when I looked at some older code of mine after a couple of month, it was quite hard to comprehend due to the first and second parts. Not even talking about tuple which I would advise to stay away from as much as possible
@anitaig05
@anitaig05 4 жыл бұрын
love the casual setup! Makes me wanna come over and sit next to you while you explain things :)
@miteshsharma3106
@miteshsharma3106 7 жыл бұрын
Now would be a really good time to make a video on templates , because people who know c++ templates are gonna get this, but otherwise ..... Its must be like what's goin on man!!!!
@jaqb17
@jaqb17 7 жыл бұрын
yesss templates!
@TheCherno
@TheCherno 7 жыл бұрын
Coming Soon! (TM)
@sander_bouwhuis
@sander_bouwhuis 5 жыл бұрын
Interesting... I came to the same conclusions as you a few years back when checking the c++11 specifications. Thanks for informing us about your views.
@perfectionbox
@perfectionbox 5 жыл бұрын
Generally against returning pointers from functions using operator new, because now the caller has to remember to call delete at some point. Although you could use std::move with a unique_ptr
@marshallsweatherhiking1820
@marshallsweatherhiking1820 Жыл бұрын
If Im returning a big complicated class I’ve built inside a function, I always define a new type that wraps the class in std::unique_ptr and return that created type. Writing move constructor/assignment functions does almost the same thing but its more tedious. The only downside is you might get better performance writing the constructors/assignments assuming the compiler will optimize away any copying/moving. I assume moving and dereferencing a unique_ptr isn’t much overhead though, since when you’re returning something big it usually isn’t in the inner-most loop where it would matter.
@miguelfernandosilvacastron3279
@miguelfernandosilvacastron3279 6 жыл бұрын
Passing parameters it gives the impression that they are inputs. But, after you passing the beginner level, you can see the underlying flow and see that it can be used to pass multiple outputs. I agree with you. I think this is the best option, because it is simple to identify, if you choose a readable name for your parameter, and it is the fastest.
@TheVralapa
@TheVralapa 5 жыл бұрын
Structured bindings from c++17 makes the tuple part a little nicer :)
@aubertducharmont
@aubertducharmont 2 жыл бұрын
A very nice video, explanation. I would like to mention that if you are precise, the function that takes non const reference as argument and return nothing is the most performance friendly.
@CriticRoshun
@CriticRoshun 3 жыл бұрын
My favorite ways are 1. Passing by Reference and 2. Using the struct. Nice video thanks!
@ren69ade
@ren69ade 7 жыл бұрын
I agree with you, returning struct seems like the best way. I also like 1st two methods, passing references/pointers as inputs and making updates to them in function. Other stuff you showed gets confusing quickly, mostly because I'm not that familiar with c++ library features. They keep adding new functionality I never seen before.
@sanjayshr1921
@sanjayshr1921 7 жыл бұрын
To be honest this's the best setup :) and not even about setup the damn good explanation about the topic before diving in it, awesome.
@derivepi6930
@derivepi6930 6 жыл бұрын
You can enumerate the tuple position value to make it somewhat readable - std::get(John) - John is the tuple and "enum person(age = 0, ...)" for the enumerator
@derivepi6930
@derivepi6930 6 жыл бұрын
the built in library functions come with the tuple
@derivepi6930
@derivepi6930 6 жыл бұрын
You can't conceive of an instance where one of the tuple library functions might be useful? Of course I like the struct semantics better and if I wanted to use the built in tuple functions I'd probably wrap it in a struct for semantic reasons. But, for drive-by programming, the enumerated tuple could work (as could the unenuerated tuple as used in the video).
@koungmeng
@koungmeng 5 жыл бұрын
8:05 you should put: return new std::string[2]{vs,fs}; because: return new std::string[]{vs,fs} gives me an error " error C3078: array size must be specified in new expressions"
@broly4988
@broly4988 6 жыл бұрын
I recently discovered std::pair at work. I've been using maps and I must say I really enjoy std::pair for that application.
@k-tech2937
@k-tech2937 3 жыл бұрын
IMHO structs are the most natural and reliable way of handling functions with rich returns. Funnily enough that what I see most people who are not this advanced in c++ do. I feel like some very experienced people sometimes do things syntactically more complex just for sake of showing of 😃
@manuelkoch2659
@manuelkoch2659 4 жыл бұрын
the struct solution is definitely the best way to solve this for huge amount of variables and calling by references is the best for variabel num up to 3
@TheSynthesium
@TheSynthesium 4 жыл бұрын
We will be able to return multiple values asynchronously in C++ 20 using coroutines. It would be great to see your opinion and explanation of those new features, after the new standard release.
@supersquare
@supersquare 4 жыл бұрын
Thanks for sharing, I definitely need to read up on C++20
@xeridea
@xeridea 3 жыл бұрын
I think for generic stuff, pair and tuple is fine, though tuple syntax slightly clunky, and feel triple and quads should be a standard thing. For stuff used a lot, struct makes sense, but if I have a function called once or twice, I would just use a pair. Pass by reference would be the fastest, and preferred way in performance critical sections, but I don't like cluttering up function call if don't need performance.
@jackthehammer2245
@jackthehammer2245 7 жыл бұрын
Cool. Thanks to make life easier. Enum is also good for return type.
@sakuraema914
@sakuraema914 4 жыл бұрын
10:05 being said std::array is allocated on stack, 8:55 why won't it be a dangling pointer out of the function scope as if I were to return a int* which maybe holds a int arr[] ? I am guessing this std::array will have a copy to another memory location which maintain the values inside?
@sakuraema914
@sakuraema914 4 жыл бұрын
@Peterolen thx
@F1nalspace
@F1nalspace 7 жыл бұрын
I personally hate std::tuple, std::pair, std::array, std::vector or array for return types like you do as well - i just use structs for multiple return types. It works fine and its totally clear what this function will return. Even for arrays i use a struct to include the number of items as well.
@h.hristov
@h.hristov 7 жыл бұрын
Really enjoyed the style of this video, thank you!
@bargainbend
@bargainbend 3 жыл бұрын
Hey Cherno, love your videos! In last part where you explained struct is the best way to return two values, how did it work by just returning { vs, fs} without allocating it into the heap?
@QIZI94
@QIZI94 7 жыл бұрын
I know VisualC++ or studio endup using the newest standards the last. But there is new way of handling it in C++17 via auto keyword, maybe wroth looking into when it will be added to non-preview version of visual studio/c++.
@Strikerz0r
@Strikerz0r 7 жыл бұрын
Could you do a video about exception handling and / or scheduling and mutual exclusion?
@flopaz6950
@flopaz6950 7 жыл бұрын
Shayan Shajarian Look in cs 162. Best OS course!
@heisenburger311
@heisenburger311 3 жыл бұрын
at 10:05, array on the stack, vector on heap. Can somebody tell me why it is?
@aarondewindt
@aarondewindt 4 жыл бұрын
How about tuples and pairs using std::tie and structured bindings?
@rajshah4376
@rajshah4376 3 жыл бұрын
Why can't we create a static array and return it in a function with a return type of array? Please help. Thanks.
@Evan490BC
@Evan490BC 3 жыл бұрын
You can, but this is not what the video is about: it's about returning multiple values of a *different type* .
@JaymzBond
@JaymzBond 5 жыл бұрын
I create typedefs when parameters of same type are used for different things. This way it is easier to distinguish them. For example: typedef string Username; typedef string Password; void CreateUser(Username un, Password pw) Or use it as 2 parameters for your tuple in the video.
@edenpanigel
@edenpanigel 6 жыл бұрын
THE LAST OPEN-GL AND THIS EPISODE WAS VERY DIFFICULT FOR ME . JUST TO SAY THAT I FOLLOWED YOU FROM SCRATCH BUT THIS ONE WAS A LITTLE MIXED STUFF . I DIDN'T UNDERSTAND THE SYNTAX MAYBE ITS TEMPLATES...
@mohammedbarsi
@mohammedbarsi 5 жыл бұрын
I'm new to C++ (coming from Python), going through standard lib i checked library, I think its the most comfortable way to build multi-value return in C++, and its syntax compatible with C++ 17 (structured Binding), ``` #include std::tuple get_somthing() {return std::make_tuple(2, 3.3f, "abc");} then you call the above function like this: auto [a, b, c] = get_somthing(); //c++17 int a; float b; std::string c; std::tie(a, b, c) = get_somthing(); //c++11 ~ < 17 ```
@DanielLiljeberg
@DanielLiljeberg 6 жыл бұрын
You said that std::array would allocate its space on the stack instead of the heap and std::vector which would make returning std::array faster. But, depending on implementation and compiler, wouldn't that depend on the number of elements? If it's allocated on the stack and returned the actual elements. The vector on the other hand doesn't that usually (implementation specific I assume) store like a pointer to the first actual element etc so that "definition" would be copied on return but not the actual elements (that are already on the heap and the receiving vector that takes the return value of the function could just point to those existing elements), depending on how clever the given compiler is I guess? I would go for the struct way in the example you give. I want my things to be named. Even though I can get away with it and even if I'm most likley to be the only one looking at my code I often try to think about it in a way that "IF someone else has to read this they should be able to figure it out". I have had instances where I have worked in system that has had stuff like if(ShowDialog(translator->string(156))->getReult() == translator->string(3749)) I have NO IDEA what the hell is going on. What question are we presenting to the user, what answer is it that makes us branch here??? I have to lookup translation files and understand the translation system etc. Drives me crazy and I want to murder people. Btw, JetBrains Resharper C++ edition is kind anice when one not always remembers the files something is defined in. Just write for instance "std::tuple foo;" alt+enter and let it include the file for you :)
@Hector-bj3ls
@Hector-bj3ls 7 жыл бұрын
I like passing pointers or returning structs depending in the size of the struct. Sometimes I'll combine them and pass a pointer to a struct.
@rcookie5128
@rcookie5128 7 жыл бұрын
yeah I'ld go with a struct too, if I use different types, otherwhise a vector/array has to do the job :s but really good to see other ways of dealing with this, will keep it in mind..
@davidcfrogley
@davidcfrogley 7 күн бұрын
Thoughts on passing in the struct by reference or pointer to avoid the copy?
@zxuiji
@zxuiji 3 жыл бұрын
Ironically it's quite simple for a compiler to compile multiple returns down to an anonymous struct and pass the values into the chosen variables so this: "a, b, c = func()" would compile down to roughly "push push push call func mov c +3 mov b +2 mov a +1 pop pop pop" (though in a more assembly friendly then that)
@MarcinKwiatkowski
@MarcinKwiatkowski 2 жыл бұрын
Personally I prefer to use std::tuple and using std::tie() to organize return values. Or using auto [a, b, c, d] = get_data();, but unfortunately I'm not allowed to use this, because I'm tied and required to use C++11
@jeanahollings
@jeanahollings 2 жыл бұрын
I like hearing you talk about memory stuff and by extension performance. I am very likely to never professionally work in c++ but much more likely to use Java. And while I don't need to know all this, I always do better if I can "get under hood." So while what your saying doesn't definitively apply to Java, it helps me understand why Java does what it does and how it does it and knowing that will help me grok the whole thing better.
@kirillsulim
@kirillsulim 7 жыл бұрын
7:13 probably error. You return address of string placed in stack, which be destroyed at the end of function block
@kirillsulim
@kirillsulim 7 жыл бұрын
If you need to use pointers, consider using shared_ptr or unique_ptr at this case
@vikinggeorge7007
@vikinggeorge7007 2 жыл бұрын
What IF I want to return only one value, but it being one of two types? Say a string OR a bool? I use std::variant for this.
@vertigo6982
@vertigo6982 6 жыл бұрын
05:57 could one just assign ss[0].str() to vertexSource? and the same for fragmentSource.. so fragmentSource = ss[1].str(); ?
@laad
@laad 7 жыл бұрын
This is the 1st time I see you check out your phone notification. Getting distracted here a bit lol.
@tukunuz
@tukunuz 2 жыл бұрын
When struct is returned by value does that mean that it is first created inside the function and then copied when returned to calling function? Is it better to return it as a reference?
@BlackJar72
@BlackJar72 7 жыл бұрын
I almost always use the struct method, even across languages (possibly with a different name for the struct). I use passed in arguments in some cases, especially if the data was non-trivial, but would still likely wrap it in a struct or class; that would also be the one case where I might (rarely) use an array, in special, very circumstances.
@PflanzenChirurg
@PflanzenChirurg 7 жыл бұрын
ive waited so long for a continue of this c++ series
@RogerTannous
@RogerTannous 2 жыл бұрын
For std::tuple, what about putting enum ShaderType outside ParseShader(), then doing this:: auto sources = ParseShader("res/shaders/Basic.shader"); unsigned int shader = CreateShader(std::get(sources), std::get(sources));
@mikeorioles
@mikeorioles Жыл бұрын
I learned some new things! Nice video.
@LucidStew
@LucidStew 6 жыл бұрын
The optimization tidbits made the video better.
@warzonemoments3970
@warzonemoments3970 2 жыл бұрын
One thing I don't get, is in the return he initialized a struct but the struct had no parametised constructor?
@LS-cb7lg
@LS-cb7lg 4 жыл бұрын
i used an array when i was faced with returning multiple values, but the struct is a very good idea
@mm1979dk
@mm1979dk 7 жыл бұрын
struct is the right way of doing it unless you are coding a (template) library and you don't know/care how the fields are named, then tuples are handy.
@abhijeetjain04
@abhijeetjain04 7 жыл бұрын
Are you planning to make some videos on DESIGN PATTERN in C++???
@geamer0079
@geamer0079 2 жыл бұрын
I think the most optimised way would be to return a uintptr_t[] which will contain pointers to any values you want to return
@solifugus
@solifugus 2 жыл бұрын
So... back to old fashion C style structs..... or like in Golang. Yeah... but the {a,b} part makes it C++ nicer.
@rj00a
@rj00a 7 жыл бұрын
The struct way is great as long as you're not working with any crazy generic code. It could potentially get a little messy having to define a struct in the surrounding scope though.
@heisenburger311
@heisenburger311 3 жыл бұрын
at 12:25, why not use `std::make_tuple` instead?
@khatharrmalkavian3306
@khatharrmalkavian3306 3 жыл бұрын
Honestly, when I find myself thinking about busting out a tuple I usually just step back and try to figure out where my design went wrong.
@bibbisbibbis
@bibbisbibbis 3 жыл бұрын
I can't tell you how sad this makes me to hear. Tuple is such a powerful tool but so many people shy away from it simply because it's so unnecessarily messy to use.
@JuddMan03
@JuddMan03 2 жыл бұрын
if you have to write a list of types your function will return, why not just write a struct definition instead? A tuple template probably compiles down to the same thing in the end.
@StevenMartinGuitar
@StevenMartinGuitar 3 жыл бұрын
Me: It's pretty annoying that you can only ever return one thing... Cherno: Yeah so here's about 10 different ways off the dome you can do this 🤯 And that's why I'm here, to learn this stuff!
@foomoo1088
@foomoo1088 2 жыл бұрын
I prefer the struct approach as well, self documenting .
@grzesiek9514
@grzesiek9514 7 жыл бұрын
Could you show us how to make your own file format? And how to save to file etc? I would like to create something simple like list of 3D vectors in binary format.
@viraatchandra8498
@viraatchandra8498 7 жыл бұрын
When returning a stack created object like a std::vector from a function, will It be copied at the receiving end? like : std::vector a = createVector(5); //createVector(unsigned size_t size) returns randomly filled vector of size size This is the kind of place where we use Move semantics right?
@dudeperforming4188
@dudeperforming4188 7 жыл бұрын
Variable of large memory should be used by reference whatever are their number and the variable of small memory but more than one should by struct. Keep it cherno. Please tell about how file formats works making your own file formats. Mostly it is not spoken. Thanks.
@andreasoldi152
@andreasoldi152 4 жыл бұрын
In c++ 17 you can access touple like this without the get method, I don’t like it either. std::tuple tt{5,10.3}; auto &&[ff,ss] = tt; std::cout
@b4ttlemast0r
@b4ttlemast0r Жыл бұрын
This video seems a bit outdated even with respect to C++ 17, maybe it could be good to make an updated remake. Maybe when C++ 23 is out (idk if it has an impact on this).
@alltheway99
@alltheway99 4 жыл бұрын
An STL container comparison video would be cool, And main algorithms
@Spartan322
@Spartan322 5 жыл бұрын
tbf we could actually write up tagged tuples extending the standard tuples, the smoothest form I've seen it in requires constexpr and macros tho.
@meer_kat5158
@meer_kat5158 3 жыл бұрын
Hi, if std::array allocates memory on stack, how do you return it then?
@CViniciusSDias
@CViniciusSDias 4 жыл бұрын
You returned a struct so that was copied, right? Is copying better then allocating on the heap?
@adamkonrad
@adamkonrad 7 жыл бұрын
I'm a fan of passing in a variable reference OR returning a struct. The other options just don't feel right.
@casvanmarcel
@casvanmarcel 7 жыл бұрын
you are a very good teacher! thanks
@TheCalax
@TheCalax 5 жыл бұрын
Is there any perofrmance penalty using structs in c++ as a return value? In the end, you're basically just handling x bytes of memory, the size just being your content... Is there any overhead to this?
@rossdev
@rossdev 4 жыл бұрын
@Peterolen A little late to comment here, but I'm guessing Z3roFPS is referring to activation of the copy constructor of the struct as it gets returned by value vs passing two pointers or references to std::string. Modern compilers can deal with the potential copy overhead in the former case through return value optimization.
@lfernandorg
@lfernandorg 4 жыл бұрын
Hey Cherno, how's going? I studying C in college, I'm getting interested in C++, I like to see your videos, but my concern is when I compile some open-source software in Linux for example, then I execute make, configure and install, I not sure of the order of these commands, but I see for example GCC -o program_name source-code and then a bunch of options gives to GCC or g++, options that cover lines, where can I learn those options? does in real projects happen this way? I know you use Visual Studio, how does it work in VS C++ in real projects for Windows, Do you need to give a lot of options to be able to compile?
@klaxoncow
@klaxoncow 3 жыл бұрын
"Make" is its own utility. It can actually be used for a whole host of other things, as well as other languages, besides C / C++. "Make" reads a file - often named "makefile" - that essentially contains a recipe for building software. Then you just type "make" and the Make utility will run through the recipe. In the makefile, you specify a target, then a colon, then specify that target's dependencies. Then, on the next line, you hit tab - yeah, in makefiles, the whitespace is important and it's needs to be a tab character, not just many spaces - you enter a command for creating that target from those dependencies. For example: main.o: main.cpp gcc -c main.cpp -o main.o Here, "main.o" is the target - the thing we want built - then, after the colon, are the dependencies. In this case, to build "main.o", we need the "main.cpp" source file. Then, on the next line, after a tab character (although, above, I had to use spaces, as you can't hit tab in a KZbin comment), I supply a command that compiles "main.cpp" into an object file and outputs it as "main.o". Now, here's where the Make utility comes in handy. When it reads the "main.o: main.cpp" line, it sees that "main.o" is dependent on "main.cpp". So it checks the timestamps of these files. If the "last modified" timestamp of "main.cpp" is newer than "main.o", then "main.o" is out of date. So the Make utility will run the command line underneath, which compiles "main.cpp" into the "main.o" object file. But if the timestamp of "main.o" is newer than "main.cpp", then "main.o" is up to date and the Make utility will not run the associated command. The beauty of this conditional execution of the associated commands - checking the timestamps of the target and its dependencies, to see if it's out of date - is that it'll only compile what needs to be compiled to bring things up to date. On a large project, with many files and inter-dependencies, where you might also have multiple stages (source -> assembly listing -> object code -> linking final executable), then using "make" means you're not re-compiling the whole project every single time. The "Make" utility will check those timestamps and just compile what's out of date to bring it into date, and that's all. So, if you only modify one source file, then "make" will only re-compile the targets that have that source file as a dependency. Everything else is up to date, so it won't touch it. Now, there's all kinds of features and syntax to makefiles - it's kind of like a mini-programming language of its own (and, if I recall correctly, it is technically Turing complete) - to make recipes easier, to use variables, to cache a file's "#include" files to do auto-dependencies for you and a whole host of other things. For example: %.o: %.cpp $(CC) $(CCFLAGS) -c $< -o $@ This is a generic "compile .cpp files to .o files" command. The "%" is a wildcard, matching any filename (so, "%.o" is all ".o" files, and "%.cpp" is all corresponding ".cpp" files). I'm using variables with "$(CC)" and "$(CCFLAGS)" - which is a common thing in makefiles to define the compiler as "CC" and the flags as "CCFLAGS" at the top of the file, so you can switch to using another compiler or add an extra flag to all compilations by just changing the variables - and the macros "$
@sayedreda3694
@sayedreda3694 2 жыл бұрын
I actually like using the struct more because it's organized and easy to read and also using vector using tuple maybe I didn't get so I kinda hate it since i follow the series of openGl
@ashutoshrautela3454
@ashutoshrautela3454 7 жыл бұрын
Cherno... Really wish to see a rendering engine developed using multithreading.. Is it possible.. If yes.. How fast it would be in comparison to single threaded? What would be the complexity..
@TheCherno
@TheCherno 7 жыл бұрын
Theoretically twice as fast. When we get to the game engine series it will be multi-threaded, though I suspect I'll also cover this as part of the OpenGL series later on.
@ashutoshrautela3454
@ashutoshrautela3454 7 жыл бұрын
Great
@manimax3
@manimax3 7 жыл бұрын
I dont know which standard you are using but Structured Bindings would be the best option in my opinion.
@TheCherno
@TheCherno 7 жыл бұрын
It's extremely new and not really supported everywhere yet, so I tend to avoid it.
@Xspacecho
@Xspacecho 7 жыл бұрын
would you do the video of recursion ? really have difficulty mastering it
@andrewnorris5415
@andrewnorris5415 2 жыл бұрын
Q. Why do you not use it much yourself? Return via. structs and pass by ref?
@reubenfrench6288
@reubenfrench6288 7 жыл бұрын
Could you explain how memory management works at the hardware level? The heap has never really made sense to me.
@ihnwtpu
@ihnwtpu 7 жыл бұрын
It seems that it's also possible to do it the struct way like this: struct { std::string VertexSource; std::string FragmentSource } ParseShader(...) { ... } Does anyone know if that's intended or it's just a random feature that happens to work? Visual Studio underlines it but it compiles and works just fine, interestingly. I couldn't find anything online, probably because I don't know what to search for though.
@antiHUMANDesigns
@antiHUMANDesigns 7 жыл бұрын
Are you defining an anonymous struct as the return type of a function? Because that should absolutely be illegal according to the C++ standard. I remember the standard clearly saying that exactly this is illegal. Well, it doesn't say "anonymous", only that types are not to be defined in the return type. I'm not sure it makes a difference. I tested it in VS2017, and I get errors.
@ihnwtpu
@ihnwtpu 7 жыл бұрын
Interesting. For me, VS2017 complains "cannot overload functions distinguished by return type alone", even though it's the only function with that name, but it compiles and runs just fine.
@antiHUMANDesigns
@antiHUMANDesigns 7 жыл бұрын
Yes, same error for me, when I tried it. But it's weird if it works, as it is directly forbidden by the C++ standard, I'm quite sure. So, even if it works, I highly recommend that you don't do that.
@P4nDA_pls
@P4nDA_pls 4 ай бұрын
thanks, used struct to solve my problem 😆
@nadavm
@nadavm 7 жыл бұрын
What about a templates in CPP video ?
@seditt5146
@seditt5146 7 жыл бұрын
I am on the part of the Sparky Engine #6 series attempting to load the VertSource and Fragsource and my program is crashing every time. Debug says Bad Ptr for VertSourceString. I thought my code matched yours but apparently now this is area causing the crash std::string vertSourceString = FileUtils::read_file(m_Vertpath); std::string fragSourceString = FileUtils::read_file(m_Fragpath); const char* vertSource = vertSourceString.c_str(); const char* fragSource = fragSourceString.c_str(); any suggestions?
@antiHUMANDesigns
@antiHUMANDesigns 7 жыл бұрын
I haven watched those videos, so I don't know the code, but: What happens to vertSourcesString? Because if you're taking the address from it, thought c_str(), and vertSourceString goes out of scope, it will delete the contents, and your pointers will point to nothing. So, if it will go out of scope, you need to make a copy of its content, if you weant to keep it. You can't just take its address, as the thing it points to will no logner exist, and you'll get that kind of error, where you're trying to dereference some RAM that is not reserved for anything. This is a problem of "ownership". You've got two pointers pointing to the actual text, and std::string thinks that it is the owner, so it will delete it. But you think that your pointer is the owner, so you don't expect std::string to delete it, but it does. In fact, this line: const char* vertSource = vertSourceString.c_str(); ...in completely pointless. Just keep the string object, and use it directly, instead! It's the same thing.
@seditt5146
@seditt5146 7 жыл бұрын
Yeah you copy it to a variable so that it wasn't lost. I did finally manage to fix it last night then ended up with a shit load of other linker errors not even 10 minutes later. Now I will have to watch pretty much every video all over again in order to find out what Namespace/Include I have out of order. C++ linker errors are a pain in the ass anymore if you need 2 files to include the same header. #ifndef does not always seem to work. std::string vertSourceString = FileUtils::read_file(m_Vertpath); std::string fragSourceString = FileUtils::read_file(m_Fragpath); const char* vertSource = vertSourceString.c_str(); const char* fragSource = fragSourceString.c_str(); glShaderSource(vertex, 1, &vertSource,NULL); My error was coming from multiple fronts C++ seems to not read C:\User folder.. As a result it wasn't finding it. On top of that I am running a different version of OpenGL then what he has so I had to totally rewrite my shader code. I posted my solution on that video in case it helps other.
@seditt5146
@seditt5146 7 жыл бұрын
""In fact, this line: const char* vertSource = vertSourceString.c_str(); ...in completely pointless. Just keep the string object, and use it directly, instead! It's the same thing."" How would u suggest it the written? Last time I programmed C++ was 15-20 years ago on DOS. Iv been beyond confused lately which isn't like me.
@antiHUMANDesigns
@antiHUMANDesigns 7 жыл бұрын
Oh, my bad, the function glShaderSource() actually takes a pointer-to-pointer-to-char, not just a pointer-to-char, so that you can supply an array of pointers. "#ifndef" include guards do work, so don't worry abotu that. If you're on Visual Studio, you should use "#pragma once", though.
@seditt5146
@seditt5146 7 жыл бұрын
Using Pragma, still getting a mess of linker error if the headers are called on multiple cpp files. Never had any issue like this years ago so its uphill battle to say the least'
@hamidrezaarzaghi7349
@hamidrezaarzaghi7349 6 жыл бұрын
@TheChernoProject Mr. Bjarne Stroustrup (Creator of C++) stated in his book (the c++ programming) over thousand times that prefer std::vector over std::array and even over C style arrays and he stated that it doesn't have any significant overhead in comparison to even C style Array. He stated that use std::vector as your default array container unless you have a good reason to choose another array container in c++. I really confused, it seems you're right and it has a lot of overhead specially in push_back method. but why Mr. Stroustrup strictly advised to use std::vector??? thank you for the amazing play-list
@groberti
@groberti 6 жыл бұрын
It does have a huge advantage if you don't need the absolute best performance available: it is much, much easier to work with and you won't have to use indexers
@TealJosh
@TealJosh 4 жыл бұрын
std::vector is ultra safe. And it's actually not recommended to use push_back() unless it's absolutely required. Define the vector, use resize() method to set it into the approximate size you'll need it to be and then use it like any other dynamic array. When you use optimizations("Release" in visual studio, "-O2 or -O3" in clang++ and g++) it really does achieve near std::array speeds and is exactly as efficient as c-style dynamic array.
@tanh8285
@tanh8285 7 жыл бұрын
Great video as always!!!! Could you make a video about time complexity in C++?
@flflflflflfl
@flflflflflfl 2 жыл бұрын
How is time complexity related to C++?
@dylangrace1239
@dylangrace1239 2 жыл бұрын
The fast way… __asm__ (“mov Var1Reg, %%eax;” “mov Var2Reg, %%ebx;”); With an ASM function call on the other side to manage placing them where they need to be (or you can just place them there as your return if you know where you want them beforehand) Pretty ugly, but should be very fast because it can keep most of you data types in registers instead of pushing them to the stack This could be a poor choice of registers because it’s been a little while since I’ve worked with x86 assembly, but you can find that information from plenty of data sheets online if you are actually doing it this way.
@saikirangattu2924
@saikirangattu2924 7 жыл бұрын
Great video as always, But we wont mind hearing about the optimization stuff you kept mentioning. Always felt I am missing something when you said you are not going to talk about optimizations.... I always watch your videos because they offer best practices which is more than syntax.
@Murderface666
@Murderface666 7 жыл бұрын
How would you work in a geometry shader?
Templates in C++
17:58
The Cherno
Рет қаралды 605 М.
Type Punning in C++
13:20
The Cherno
Рет қаралды 159 М.
Леон киллер и Оля Полякова 😹
00:42
Канал Смеха
Рет қаралды 4,6 МЛН
小丑教训坏蛋 #小丑 #天使 #shorts
00:49
好人小丑
Рет қаралды 47 МЛН
What I do to never have to worry about memory leaks!
8:03
Low Level Game Dev
Рет қаралды 46 М.
the cleanest feature in C that you've probably never heard of
8:13
Become a Malloc() Pro
6:58
thedoubleeguy
Рет қаралды 13 М.
The "auto" keyword in C++
17:04
The Cherno
Рет қаралды 207 М.
Ditch your Favorite Programming Paradigm
6:08
Code Persist
Рет қаралды 209 М.
do you know how "return" works under the hood? (are you SURE?)
5:08
Function Pointers in C++
12:41
The Cherno
Рет қаралды 397 М.
Move Semantics in C++
13:10
The Cherno
Рет қаралды 305 М.
Should you learn C++?? | Prime Reacts
20:29
ThePrimeTime
Рет қаралды 406 М.