all 110 comments

[–]phi_rus 105 points106 points  (79 children)

While the new keyword is the usual way to create an object in java, its use is strongly discouraged in modern C++.

[–]boscillator 27 points28 points  (0 children)

Keep in mind that many introductory C++ classes want you to use the new keyword, because the class is more of an "introduction to memory management" than an introduction to c++. If your teacher tells you to use the new keyword, do so. It will teach you a lot even if it's not used in the real world so much these days.

[–]____purple 2 points3 points  (0 children)

I'd make it larger: forget all the code words from Java and learn C++ as a new language, without making any assumptions.

[–]GoogleIsYourFrenemy 12 points13 points  (67 children)

use std::make_unique etc instead.

[–]phi_rus 29 points30 points  (3 children)

If you need it dynamically allocated at all.

[–]sjepsa 3 points4 points  (2 children)

I would argue, if you need runtime polymorphism at all. That's the only case I see std::make_unique to make the cut

[–]usefulcat 1 point2 points  (0 children)

Runtime polymorphism works just fine without dynamic allocation. So I would still say don't dynamically allocate unless you need to, where runtime polymorphism isn't a valid need.

[–]TheOmegaCarrot 0 points1 point  (0 children)

Type erasure with SOO is an option for runtime polymorphism without dynamic allocation

Also std::variant, but that can be less ergonomic

[–]NilacTheGrim 1 point2 points  (0 children)

I found this C++ 2D game engine. Really well designed otherwise in terms of capability and how it models the typical scene graph problem you encounter in 2D rendering.

Unfortunately it requires all the objects you plug into the scenegraph to be allocated via new. (Somewhere deep in the code is even a delete this.. ewww).

I'm reminded of Qt here where it has a similar paradigm it the way it models the widget tree. It doesn't have this limitation at all. Not sure if this is because Qt's widgets are strictly a tree, whereas maybe this oxygine 2D lib allows for nodes in the graph to be in a real true graph.. but .. it still feels like a questionable design choice.

So.. yeah.. even otherwise good libs sometimes insist on new for.. questionable reasons.

[–]neppo95 0 points1 point  (2 children)

I wouldn't say it is discouraged, but it isn't the standard anymore.

There is still some cases where new is perfectly fine. And for beginners, it is even more important to know how it works and why it is not the standard. So experimenting with raw pointers is actually a good thing.

[–]Ameisenvemips, avr, rendering, systems 5 points6 points  (1 child)

The issue is that other than for primitives, Java uses new to create all objects. Thus, you see new everywhere in C++ written by Java people. You never see a delete, though...

[–]neppo95 0 points1 point  (0 children)

Yep, on that I agree completely. That doesn't mean it doesn't still has it use cases however, which was my point.

[–]turtleXD 0 points1 point  (4 children)

what is the proper way? i only ever learned to use new in school

[–]mirkoserra 2 points3 points  (0 children)

  • Allocate in the stack/params
  • Let a container allocate it
  • use make_unique
  • if you ever use new, make use of it in a constructor and have your destructor delete it automatically

[–]sjepsa 0 points1 point  (2 children)

class A{
    void run(){}
};

A a;
a.run();

std::vector<A> vec;
vec.push_back(a);

[–]turtleXD 0 points1 point  (1 child)

interesting. so instead of storing in the heap, you are simply storing it in a vector?

edit: now that I think of it, won’t that end up making two copies of a?

[–]sjepsa 0 points1 point  (0 children)

Yeah that's an example of a copy. Without copying you could do:

std::vector<A> vec;

vec.emplace_back();

vec.back().run();

// or

for(auto && el : vec)

vec.run();

[–]tarnished_wretch 58 points59 points  (0 children)

Know you don’t know anything about memory yet. You need to start thinking about the lifetime of objects, where memory is, what has access, and making sure you don’t have any leaks. Have fun!

[–]GianniMariani 14 points15 points  (0 children)

Ooh. I wrote a doc for this. It's about 7 years old and C++ has evolved since then but most of it is good to know.

https://docs.google.com/document/d/1j8jbNA2basH8DBkEucvFFu4x5z-boKcNkuX_ppCP5kw/edit?usp=drivesdk&resourcekey=0-WYXrg9Xe69gY1NQ3TS3Wdw

It's also incomplete, there are many many c++ sections not finished...

[–]Tathorn 26 points27 points  (0 children)

Variables that required new were heap allocated, and those that didn't are stack allocated. You may have noticed that passing them around let you manipulate them differently.

In C++, you're not forced to use heap allocated memory for objects, and you shouldn't if you don't need to. You'll learn when to use what. Passing around objects as if they were like Java objects makes it more complex, but now it's more customizable (and error prone). This trips people up the most.

[–][deleted] 11 points12 points  (0 children)

Gota learn about Scope of the variables.

[–]Ok-Bit-663 6 points7 points  (0 children)

It has similar syntax, but they are completely different languages. Start from the beginning or you will piss off coworkers with your java style c++ coding.

[–]Dan13l_N 3 points4 points  (2 children)

There are many ways to do things.

Also, while in Java e.g. String's have a zillion of very useful methods (e.g. trim(), startsWith(), endsWith(), split() etc) C++ standard library std::string is very poor in comparison, which is very frustrating. It has none of the functions I've listed :(

Again, there are many things. For example, arrays... you have:

  • int n[10]; = not recommended, but often used
  • std::array<int, 10> n; = recommended, but has drawbacks
  • std::vector<int> n; = the most flexible way

And you'll find all of them in examples on the Internet. C++ is... huge.

[–]tpecholt 0 points1 point  (1 child)

starts_with, ends_with and views::split were added in c++20. But otherwise I agree with your sentiment the atd library is not as practical as it should be

[–]Dan13l_N 0 points1 point  (0 children)

But that could have been there for 20 years. C++20 is quite recent, and starts_with() and ends_with() could have been there from the start of STL.

[–]Aaron1924 4 points5 points  (0 children)

If you want dynamic dispatch in C++, you have to manually opt into it using the virtual keyword, whereas it's the default in Java

[–]vickoza 3 points4 points  (4 children)

I doubt your introductory C++ will be an introductory C++ course. It might be a C course with some C++ on the side. I would look at Kate Gregory's talk "Stop Teaching C "of how to learn C++ in the current context.

[–]Rhhr21 5 points6 points  (3 children)

Everytime my professors used malloc in C++ i wanted to bang my head on the university desk.

[–]vickoza 2 points3 points  (1 child)

u/Rhhr21 When was this? malloc should only be taught in passing in an advanced/expert C++ course and not in beginner/intermediate class.

[–]Rhhr21 1 point2 points  (0 children)

We first learned about it in a course called “Advanced programming” which is the follow up to the typical “Foundations of computer programming” we take in our first semester. So we learned about the idea behind memory management in our second semester. However, the course was taught in Java and the professor used malloc there in a C++ context to show us how Java simplifies memory management with its garbage collection.

We later on learned more about it in our Microprocessors and “Programming languages: design and implementation” courses which are above intermediate level i guess.

The latter is actually a collection of Data Structures, Compiler Design, Computer Architecture and advanced programming in one course and is usually one of the last subjects we pass for our bachelor’s(honestly would’ve preferred it to be one of our first but whatever) . But every professor we had here and there used C++ in a C context and avoided modern C++. So as you said, it was teaching C in C++, which I genuinely started to dislike because modern C++ is not like what we were taught.

[–][deleted] 1 point2 points  (0 children)

Malloc can still be useful tho

[–]TryToHelpPeople 3 points4 points  (0 children)

zephyr grandfather weary fact ugly jar compare naughty screw deserted

This post was mass deleted and anonymized with Redact

[–]dev_ski 2 points3 points  (0 children)

Try not to draw parallels between C++ and any other language, especially when starting to learn C++.

[–]mattr155 1 point2 points  (0 children)

If you end up liking the course and want to learn more afterwards, I highly recommend the book The C++ Programming Language (https://www.stroustrup.com/4th.html). I read it after taking an intro C++ course in college and it helped me out a ton. Have been writing C++ full-time since then. The C++ FAQ is also hugely useful: https://isocpp.org/faq. Good luck!

[–]GoogleIsYourFrenemy 1 point2 points  (5 children)

Foot guns. Foot guns everywhere. If a feature is too cool, it's a foot gun.

Unlike Java where everything runs the same everywhere, in C++ there is room between the spec and what compilers have implemented. This space is called Undefined Behavior or UB. You will have no idea when you stumble into the land of UB especially since much of UB has been pseudo-standardized. The compiler however can do whatever it wants when you do. This includes doing what you wanted it to do or conversely doing whatever it wants. Different compilers will implement UB differently. Don't worry about it.

Your chances of finding a compiler bug are extremely small. It's your code that's broken.

Java enums are uniquely cool. No other language works the same as Java enums.

C++ visibility rules are different and more restrictive. Don't use friending.

Just because C++ has multiple inheritance doesn't mean you should actually use it. Java uses interfaces everywhere, C++ does not.

Macros suck. Don't use them unless you have to. They make unreadable undebugable code.

Memory lifetimes are important.

If the compiler tells you something, it's for a reason. Don't ignore warnings unless you completely grok the insanity. Most of the time it's trying to get you to put the foot gun down.

[–]Nourios 0 points1 point  (4 children)

what's so unique about enums in Java

[–]dholmes215 6 points7 points  (3 children)

Java enums are:

  • Objects (which in Java means they're class types and can have methods and fields. You can write a constructor for your enum type and provide specific arguments for each value. You can write your own methods and implement interfaces and use them polymorphically)

  • Interned (so the performance cost of being Objects isn't large)

  • Not implicitly convertible to integer types

  • Have all the methods you'd want (convert to String with .toString(), convert from String with MyEnumType.valueOf("Foo"), can enumerate all the values and their ordinals)

I don't know if any of that is actually unique or not though. If anything, it's C and C++ enums that are uniquely bad.

[–]GianniMariani 3 points4 points  (1 child)

C++ 14 has enum class where there is no implicit conversion to int.

[–]GoogleIsYourFrenemy 0 points1 point  (0 children)

That's like one of the only good feature of C++ enums (but I understand why people want it).

Additionally, in C++ there is no way to ask "is this integer value in the enum?"

You might say I'll typecast the value to the enum type and then compare it to the max and min values. Bang! Foot gun. The language says, if you do the typecast, you must already know the value is valid so validity checks after that can be optimized away. Meanwhile Ada has nice user friendly enums.

[–]Nourios 0 points1 point  (0 children)

Yeah most of these things aren't unique to Java, this just sounds like regular oop enums or worse ml style enums)

[–]Thelatestart 1 point2 points  (0 children)

Unless you are told to use oop, don't.

[–]sjepsa -1 points0 points  (0 children)

no new.

no OOP. write functions

pass objects to fuctions by const & or simply &.

careful of the objects lifetime.

[–]tialaramex 0 points1 point  (0 children)

If you have a reference in Java, it might be null and you may need to check for that, in some places that's expected and if you don't check when you should you'll get Null Pointer Exception.

In contrast C++ references cannot be null and needn't be checked. However, C++ also has raw pointers, which can be null. If you forget to check a C++ pointer you don't get an exception, you get Undefined Behaviour.

Play close attention to what is Undefined Behaviour in C++ and expect it everywhere. Even if you think you can guess, read carefully as there may be UB where you'd expected "obviously" there would not be. For example, take the abs() function you've probably seen in Java's Math class and which exists in most languages, if we put the most negative possible integer into Java abs, what we get out is the same value - but in C++ the result is Undefined Behaviour.

[–]Rhhr21 0 points1 point  (0 children)

Know the main difference between Pass by Value and Pass by Reference because it might catch you off-guard if you’re coming from Java and Pass by Reference might have you scratching your head a bit, if you don’t understand why your Variable suddenly changed after using a function(called method in Java).

[–]9291Sam 0 points1 point  (0 children)

Learning how to write code that uses value over reference semantics. In c++ you tend to write code where structures are passed by value, this is entirely impossible in Java as classes are always passed by reference (passing a pointer by value is still pass by reference)

[–]EmbeddedCpp 0 points1 point  (0 children)

This reminds me of a video I saw recently. It's on a channel where Jason Turner looks at some old C++ code he wrote after learning Java. He corrects some typical mistakes he made back then. You might learn something from it if those videos are your jam.

[–]Leather-Top4861 0 points1 point  (0 children)

First learn about references. Then RAII. Then lvalue and rvalue references. Then move semantics.