I've heard people describe C as a better assembler, but that doesn't make it a poor language to learn.
Quite the opposite. This is why it is an excellent language to learn as you gain true insight into the low level behaviour of the machine that higher level abstractions deny you.
I've never met a skilled C/C++ developer yet that writes inefficient or sloppy code regardless of the language they are using. In my experience, the same cannot be said for those that come purely from higher level language backgrounds.
Languages that require you as the developer to take ownership of efficiency and resource management tend to be the best to learn. Languages that take over resource management are good once you understand how said management works.
I regularly see things like this in java code:
while (isNotDone()) {
Something blah = new Something();
// ...
blah.doSomeOperationThatDoesntAlterObjectItself();
// ...
}
in places where
Something blah = new Something();
while (isNotDone()) {
// ...
blah.doSomeOperationThatDoesntAlterObjectItself();
// ...
}
would perform the exactly the same job. The developer is utterly oblivious to the cost of repeatedly constructing an object that gets used in a non-destructive way once. Instead, all they know is "best to keep variables as local as possible" because they have not learned anything about resource management since they have never used a language where they are required to manage resources themselves.
From a high level, their code is well structured, very OOP, properly implementing known patterns where they apply but the physical implementation of their code is full of inefficient resource clobbering examples like those above.