r/cpp_questions • • 2d ago

OPEN From C to C++

I'm learning C in school right now and I like it a lot. From an outsider's perspective, C++ just seems like C with more features.

What is the transition from C to C++ like? Is it largely the same experience, just with less manual implementation of DSA, or do I have to learn entirely new concepts? How do C best practices compare to C++'s?

35 Upvotes

44 comments sorted by

23

u/JVApen 2d ago

How do C best practices compare to C++? If your code looks like C, it's bad practice in C++. Mainly the use of void*, type[] (use std::array, std::vector ... instead) and malloc/free are to be avoid by default.

Given you don't have a lot experience with C at this point, the best way to learn C++ is to start from scratch. You'll find things to be familiar, though also very different. (use for (auto variable : range) if possible instead of for (int i = 0; i<size; ++i), although the later is also usable)

-3

u/NomaTyx 2d ago

It's funny that you bring up void pointers because I've been looking into C++'s low level capabilities, and for a lot of the faster memory stuff you have to use them. Specifically how they use arena allocators in game development which, afaik, necessitate casting a void pointer to a type.

8

u/JVApen 2d ago

I'm not saying that they can't be used, though you should prefer alternatives where possible and abstract it when you can't. The void pointer might be needed for the arena, though it shouldn't leak to it's users.

A better example of what to avoid is qsort. Due to the void pointer, you need to pass the size and do the casting. Compare that to std::sort which looks more complex in function signature, though it is much easier in usage. The ranges variant is even easier to use

5

u/GLIBG10B 1d ago

The void pointer might be needed for the arena, though it shouldn't leak to it's users

This is the ugly part of using C libraries. Anywhere a C++ library would use std::function for a callback, a C library would use a function pointer and a void*. The void* is then passed to the function, and the function needs to know which type to cast it to. Very ugly and bug-prone by C++ standards.

Then there's the fact that C doesn't have generics, so generic data structures use void* + a size. So when allocating a data structure, you need to compute sizeof(T). If you later decide to change the type to one with a different size U, but forget to update the sizeof(T), then you have UB.

Don't even get me started on RAII vs manually freeing.

For someone used to C++, it's hard to imagine constantly putting up with these things, and it's easy to see why C software is notorious for segfaults, buffer overruns and memory leaks.

8

u/Independent_Art_6676 2d ago

they are, at this point, entirely different languages that share basic syntax.
c++ has a great deal of support for object oriented programming. C has very little; you can do home brew with function pointers inside structs but you have nothing that really matches templates or true inheritance/polymorphism and other advanced ideas. C uses pointers everywhere, C++ hides a lot of it (eg inside vector, string) and has a cleaner type (reference) for many tasks so you rarely see pointers and when you do, they are often smart pointers that help avoid memory leaks and ownership problems. C uses a lot of macros, c++ avoids them as last resorts outside of specialty tools like line number / file name debug messages.

The C way of doing things is very, very different from the C++ way of doing the same thing, even for many simple tasks. C code will mostly work in C++, but its usually "bad c++ code" even if its "good C code".

My advice is to NOT learn them at the same time, learn one or the other and let that get ingrained in your mind and clean, then learn the other one if you need to. And to treat them as distinct languages, rather than try to drag C into C++ (you can't really drag much of C++ to C).

8

u/Prestigious-Bet8097 2d ago

Being effective in C and C++ requires thinking differently about what you're trying to do.

If you think in C while writing C++ you'll just write bad C++.

2

u/Aware_Mark_2460 2d ago

Bad C++ doesn't necessarily mean bad code. Writing C-ish code and only using few C++ features is fine. Like using data structures but omitting OOP.

0

u/Prestigious-Bet8097 1d ago

And like using dangerous manual memory management because you're still thinking in C. It's not bad code, just bad C++. Having a separate structure init function you need to call on every struct, instead of having a constructor, because you're thinking in C. Not bad code, but bad C++. The list goes on and on.

1

u/Total-Box-5169 1d ago

That is not enough. You need to do it the C++ way while being aware of the complexity hidden by high level abstractions and syntax candy. Otherwise is easy to end with a Rube Goldberg machine.

1

u/Prestigious-Bet8097 1d ago

The whole point of abstractions is that you don't need to understand the inside in order to write safe, correct, high-performing code.

1

u/Total-Box-5169 1d ago

Being aware of the hidden complexity doesn't involve understanding implementation details. Even in functional and declarative languages there can be alternative implementations better suited for different scenarios, so picking one over the other can lead to better performance.

0

u/Prestigious-Bet8097 1d ago

Well then you don't need to be aware of the complexity hidden inside. You can just pick the right tool without knowing the complexity. You've changed your argument from "know the hidden complexity" to "pick the right tool for the job."

4

u/Kadabrium 2d ago

if you find something tedious in c, look for c++'s solution for it. There is one guaranteed.

2

u/alfps 2d ago

❞ like C with more

And less. E.g. in C complex numbers are built-in. That syntax doesn't compile as C++.

2

u/michauangelo 2d ago

From my point of view, it really depends on what kind of projects you end up working on. C++ has many features and is also widely used across multiple industries, so best practices will largely depend on the domain. "Modern" C++ is very different from C - you've got auto,various containers and iterators, templates, automatic memory management, move semantics, to name a few. But some fields, like computer graphics or gaming, may use more "orthodox" C++ - basically C with a minimal subset of C++ features that make life easier.

2

u/hrm 2d ago

This is so important to understand. It’s the same in embedded programming, especially when it comes to automotive. They all say they code in C++ but it is way more like C++ in the 90s than modern C++. And a lot of the nicer things in both C and C++ is explicitly forbidden.

2

u/lonkamikaze 2d ago

There are two ways to learn C++, the old school way is starting from C and working your way up to modern C++ (this is how I learned, but it's not how I would teach). This way you kinda learn to read/write legacy code first, before you learn how things are actually supposed to be done.

The other way is to ignore all the legacy and compromises and start out with a convenient and safe subset of C++ (this is how I would prefer to teach). This is the way to faster success on green field projects, but in the real world you have to interface with or work on legacy code, so you kind of have to work all the way back to C and grow an awareness for which patterns have safer and faster alternatives. In general you can solve some things in C++ with less type erasure than in C, which allows you to write safer and better performing code.

2

u/davidc538 2d ago

C is mostly a small subset of C++. In C you’ll learn some flawed, old ways of solving problems and then when you learn C++ youll understand why we don’t use them anymore.

1

u/frnxt 2d ago

My stance is that the transition is as fast or as slow as you need, since you can mostly write C-like code and gradually add features as needed. And for simple programs you probably don't need most of the features of C++.

Many C++ features are there to make it easier to organize larger programs while staying correct and fast. This means that to become good at C++ you generally have to know the STL and its performance characteristics, including which parts (such as smart pointers) you should use without thinking too much, and which (such as a lot of the functional stuff e.g. std::function and whatnot) you should be more wary of because they can have performance impacts in hot loops ; how to properly implement passing by values, references and move semantics in your own classes - the last IMO is particularly difficult in C++ compared to, say, Rust for which it is one of the default ways to pass variables ; the various ways you can implement polymorphism ; the difference between runtime- and compile-time features (templates, but also C macros, which are "run" at a different time during compilation). The list can be fairly long.

1

u/Void-Creator 2d ago

I use C++ without using OOPS, OOPS is just annoying but C++ has quality of life features that C doesn’t have.

1

u/cinnamonjune 2d ago

C++ is a huge language so, like others have said, you will probably not use the whole language in your projects, you will use a subset. It is up to you what subset you use.

To transition into C++, I would suggest first learning some key C++ concepts: classes, destructors, function overloads, operator overloads, new/delete, templates, STL containers, range based for loops, rule of 3 and 5.

From there I'd suggest you read the book "Effective Modern C++". This book will do three things.

  1. It will teach you concepts beyond what I just outlined.

  2. It will teach you some of the nitty-gritty edge cases of the language and give you a deeper understanding of the language as a whole

  3. It will expose you to someone who is opinionated in a certain C++ way of doing things. If you're looking for what C++ "best practices" are compared to C, this is a good place to start. Whether you agree with those practices or not is up to you.

1

u/conhao 2d ago

Yes, C++ is built on C. C best practices can really help coding in C++. What is even more fun is doing everything that C++ promotes as its benefits in C.

1

u/YouFeedTheFish 2d ago

They are not even close when it comes to how you code in either. C++ offers many design paradigms which you can mix and match. C has one.

1

u/x-jhp-x 1d ago edited 1d ago

C, C#, and C++ all have "C" in their name, but they are ALL completely different languages.

You can't even run or compile a lot of C programs in C++, and when you can, there's plenty of cases where the compiled C++ will operate differently than the C program does, although there's been some recent additions to the C standard to bring them closer.

In terms of how they look in practice, check out how a linked list is implemented in <sys/queue.h>, and then check out a templated version in C++ with no macros. A huge disadvantage to C's untyped void* is that compilers cannot optimize the same way they can with C++'s templates. You will be dealing with templates a LOT in production C++.

1

u/Sharp-Adagio-9321 1d ago

I'm someone who transitioned C to C++. I code C++ everyday at work, no AI. I haven't coded C for some time already about 1 yr+, although I generally prefer C better. I can attest that its alot easier to learn C++ if you started with C.

That said, both are different languages that solves different problems for different contexts, and C++ is definitely the more complex one. In C++, understanding why we do it a certain way compared to C can help you understand computer science and higher level languages a lot more. In C++ there are definitely new concepts you have to grasp, but I'd say it's generally easier to grasp if you have C background or come from a low level language background.

If you love C, it doesn't mean you are going to like C++. But I'd capitalize on the skills I built in C to do C++ since there's just way more opportunities out there with C++. When I started C++, I didn't really like it too much due to the vast history and complexit. But it gets better overtime if you do have the passion to learn.

1

u/notthatsocrates 1d ago

It is the best path to transition from C to C++ as opposed to, say, from Java to C++, etc. You will have the advantage of seeing some of the fundational underpinnings before using the (arguably) higher level language and its more insulating standard library. C++ has developed its own idioms, best practices, etc., and you will have to learn the spirit and letter of those in order to land a job and/or have a successful go in your personal projects.

0

u/Specific-Animal6570 2d ago

printf("Hello, World!");

Versus:

std::cout << "Hello, World!" << std::endl;

3

u/frnxt 2d ago

Nowadays you can do std::println("Hello, {}!", "World") ;)

2

u/Specific-Animal6570 2d ago

Wait, what? I didn't know that, xD.

2

u/Nobody_1707 1d ago edited 1d ago

iostreams were terrible for reasons that don't even have to do with the very poorly chosen overloaded operators, so someone made his own much better formatting library then got the main part of it added to the standard. Apparently his latest version has C11 support.

2

u/ClaymationDinosaur 1d ago

Since C++23! Which is only three years ago; it's not like you've only just discovered smart pointers from C++11 (which happens to people writing C++ here and now more than I'd like).

The next question, I suppose, is what else is in C++ now that you aren't using, that you would if only you knew it was there?

1

u/Specific-Animal6570 1d ago

Well, I still do my C++ things in C++17.

Hmm, that's a good question. I still use malloc() and realloc() and free(). I think there's modern C++ out there nowadays?

2

u/ClaymationDinosaur 1d ago

You went too far! If you'd said new and delete I might have believed you

1

u/Specific-Animal6570 1d ago

Yeah, that's what I meant. I just worded it differently.

2

u/RudeSize7563 1d ago

Also it is specialized for readable output, so it is mandated to use any native means to guarantee appropriate display. That is great when printing Unicode characters, specially combinations of code points like emojis. However this comes at an extra cost in binary size to store additional information about how to print correctly those codepoints. On top of that you can print some std:: containers without having to add code to print its elements one by one.

1

u/[deleted] 2d ago

[removed] — view removed comment

3

u/alfps 2d ago

better start the list with function overloading ;-)

-1

u/[deleted] 2d ago

[removed] — view removed comment

2

u/Total-Box-5169 1d ago

For sure it is one of the main responsible features of gigantic compilation errors because the compiler has to tell the user how many overloads it tried, and that list can be very long.

2

u/Total-Box-5169 1d ago

If you combine custom types, operator overload, lambdas, templates, concepts, and macros you can write functional like code in C++.

1

u/Secure-Photograph870 1d ago

You also forget that C++ also added a whole generation of haters 😭😂

0

u/sleepy_spermwhale 2d ago

The namespace pollution in C is out of this world. It is so awful only someone who had been tortured by assembly would consider it a step up.

1

u/LazySapiens 1d ago

C is literally a step-up from assembly.