Advertisement

Unnecessary C++ features?

Started by July 13, 2000 07:53 AM
70 comments, last by null_pointer 24 years, 5 months ago
Nice thread (especially since its working )

Object creation at a specific address. Has anyone ever used this?? My guess would be that the people who need to reference a specific address use structs and C, not classes. I''ve never seen this used.

I mentioned this a little while ago, but.... Global functions/variables should have static scope by default, instead of extern. That results in less inadvertant namespace polluting.

A feature that is missing in my opinion is a realloc function for C++. I really liked that functionality, and hate doing it manually. Plus it''ll generally cause cache hiccups at least initially.

I don''t use exceptions because I just have the impression they bloat code. I have no solid reason against them, just a bias for some reason. I''ve heard they can be faster because you never have to check return codes, and 99% of the time exceptions aren''t going off. Still, they do result in some amount of extra code, and I believe that contrary to popular opinion, code bloat can slow programs down more than we like to think. Plus, I just don''t like wrapping everything in try blocks. Its not very readable to me.

Aside from that, I think C++ rocks! There are plenty of features that are misused (illogical inheritence and operator overloads, having default parameter values for things that really shouldn''t be defaulted, copy constructors being invoked everywhere instead of using references where applicable, ...), and result in poor/unreadable/buggy/unmaintainable code, but if you know what you''re doing, its VERY flexible.

Rock
re: keyword volatile & object creation at specific address & the uselessness thereof?

Two words: embedded systems. Absolutely necessary there.
Advertisement
    void main(void){for( int A = 0; A < 10; A++){}//laterfor( int A = 0; A < 10; A++){}}    


I might be misunderstanding whats going on but when I compile this code I get

error C2374: ''A'' : redefinition; multiple initialization

So does this mean that the vaiable DOESN''T have a scope that ends with the loop?

gimp
PS : Really good thread....
Chris Brodie
References:

References are just hidden pointers (not pointers to pointers), and these two functions are nearly identical in performance, are they not?


void function1(int& x)
{
x += x;
x += 3;
x *= 2;
}

void function2(int* p)
{
*p += *p;
*p += 3;
*p *= 2;
}



References basically just provide syntactic sugar. Because of the differences in syntax, pointers and references cannot be interchanged. Here''s an excerpt from MSDN 6.0a:


quote: Excerpt from MSDN 6.0a

Reference Operator: &

decl-specifiers & cv-qualifier-listopt dname;

A reference is a 16-bit or 32-bit quantity that holds the address of an object but behaves syntactically like that object. A reference declaration consists of an (optional) list of specifiers followed by a reference declarator.

In C++, any object whose address can be converted to a given pointer type can also be converted to the analogous reference type. For example, any object whose address can be converted to type char * can also be converted to type char &. No constructors or class conversion functions are called to make a conversion to a reference type.


References are also great for inline functions:


template &lttypename pointer_type>
inline void safe_delete(pointer_type& pointer)
{
delete pointer;
pointer = NULL;
}



That code allows you to treat "pointer" as the actual pointer, rather than dealing with the messy pointer-to-pointer syntax.

(now assuming 32-bit memory addressing...)

Since references are just hidden pointers, creating a reference (4-byte hidden pointer) to a char parameter to use it as a reference doesn''t make much sense. That approach would require 400% more memory, or 1/5 (sizeof(char)/total usage). It would also hamper performance, because you must access the variable indirectly (via a pointer). That''s why passing by value is the default: simple, fast, and efficient with the intrinsic types.

For large objects, the use of pointers (and thus references) is justified by the reduction of the parameter to 4 bytes. That is, if the object you wish to pass is 128 bytes, then a reference (4-byte hidden pointer) doesn''t make much difference; the increase would be a little more than 1.03%, which reduces the amount of memory required for that object copy by about 96.77% (120/124 bytes).

For small types, like the intrinsic types, the additional cost of using a pointer (both speed and memory) is not going to be justified; your purpose would probably be better served to simply widen the scope of the variable, making it a namespace variable or a module variable, which would eliminate manipulating the function''s local stack altogether.


Keyword auto:

I think that the auto keyword is a left-over from the days when the stack was considered slow. You had to explicitly declare stack variables as "auto."


Private derivation:

class A : B is allowing objects of type B to be transferred to functions requiring objects of type A, and the private keyword indicates that the interface of the derived class is totally different from that of the base.


Overloaded operators:

quote: Original post by RWarden

In fact I refuse to use iostream simply for that reason.. when I see >> I see a right shift, not stream input!


Why do you expect the << operator to act the same on both ints and iostreams?

That''s just not feasible. Operators were created by humans as short-hand notation for the properties of the data types involved. Operators are overloaded in both algebra and C with different number types - saying they shouldn''t be overloaded seems rather silly. If you check a good algebra text on the subject, you''ll find that the "laws" like commutative and associative are just properties of the data types involved, not common to the operators. Check out matrix math for an example of this. Different data types require different implementations for their operators, and operator overloading seems like the only non-redundant way to do it.

Look at the following expressions:


int x = 5, y = 10;

int z = x + y;



Without operator overloading, I see only two ways in which those statements could exist in any language: either reserve the + operator only for ints, or make different names for each operator for each type, like:


int x int_assign 5, y int_assign 10;

int z int_assign x int_addition y;



which seems redundant...shouldn''t the compiler know the types already? What is the use of type-checking, if not to control the way data is stored, and the operations on that data? That''s what data types are all about. Function/operator overloading is just a very clean way of doing it.

The difference between C and C++ operator overloading lies in C''s limitation. The only fully functional types that C allows are the intrinsic types. C structures were merely a way of grouping data together - they constitute a severely limited type (no special functions, no constructors, no cast operators, no overloaded operators, etc. nothing like the intrinsic types). In C++, a type is anything that you can define with class, and class-defined types have all the capabilities available to them that the intrinsic types have in both C and C++. That''s why user-defined operator overloading exists in C++.


gimp: The for() loop scoping rules are new - VC is not new.

BTW, you can emulate it if you want:


void main(void)
{
{
for( int A = 0; A < 10; A++){}
}
//later
{
for( int A = 0; A < 10; A++){}
}
}



But that''s kind of messy...




- null_pointer
Sabre Multimedia
Stoffel: volatile is critical. Classes at specific addresses are not. Everyone I''ve seen either uses structs, or creates a wrapper class with a struct pointer inside of it, which points to the specific address. You can try to say that it may be helpful (I do embedded stuff, and I''ve never seen it used. Though we generally use C due to size constraints), but there is no situation where it is needed.

Rock
There are no useless features, you just haven''t figured out where a specifiec feature is useful in. Volatile/static, for example, are simply critical in embedded design.

topgoro; If VC really compiles simple "a+=1" to three asm instructions, consider swithing to a better compiler... Borland compiles that to one instructions, even with no optimizations enabled... (and with optimizations whole damn line was optimized out as it''s result was not used...) (am I flamebaiting here?)
...
No wonder VC is said to optimize better. If unoptimized code is generally as lousy as that, optimizations really can do wonders...

wilka; BCB4 does support "export". However, it''s "unimplemented" according to the docs..
~~~ "'impossible' is a word in the dictonary of fools" --Napoleon
Advertisement
Rock2000:

quote:
Object creation at a specific address. Has anyone ever used this?? My guess would be that the people who need to reference a specific address use structs and C, not classes. I''ve never seen this used.


This is often used by container classes, like std::vector. It reserves a block of initialised memory then uses placement new to create new objects inside the the raw memory (so adding objects to the vector doesn''t require memory allocation, unless there isn''t enough raw memory left).


quote:
A feature that is missing in my opinion is a realloc function for C++. I really liked that functionality, and hate doing it manually. Plus it''ll generally cause cache hiccups at least initially.


If you use std::vector you dont need realloc, and it''s just as fast as using a raw array.
I love operator overloading dearly, but it really annoys me when people overload an operator to perform something completely unintuitive. I understand your point, that operators are only there for our convienence and we might as well use them (more readable than endless function calls), and that logic is fine in many cases, especially when you''re working alone. But when writing classes that will be used by a lot of people you should definitely avoid overloading operators to give them completely new meaning. Lets say I''m using a class you wrote and I see in the header file that you overloaded the + operator. So I''ll write my code to take advantage of this operator.. and only after an extended period of debugging will I realize that your overloaded + operator performs something OTHER than an intuitive addition operation.

Yeah I know, the answer to this problem is well documented code. But, and this is especially true for very large classes, generally I''ll have better things to do than read through the entire documentation for every function.

Anyway I just think overloading operators to have intuitive meaning is simply an extention of logical variable/function naming. You wouldn''t name a matrice multiplication function Add . Sure, it''s an extreme example, but you get the idea.

-RWarden (roberte@maui.net)
(Think it''s funny that every single so-called ''useless'' feature I listed down was defended.. except MFC ).
MFC ROCKS!

( Happy now, RWarden? )

I actually do use MFC a lot, because I know it, and it makes certain things to do with Windows User Interfacing a lot easier. For windowed, office-type apps, it''s a godsend, let me tell ya.


Give me one more medicated peaceful moment.
~ (V)^|) |<é!t|-| ~
ERROR: Your beta-version of Life1.0 has expired. Please upgrade to the full version. All important social functions will be disabled from now on.
It's only funny 'till someone gets hurt.And then it's just hilarious.Unless it's you.
quote: Original post by MadKeithV

MFC ROCKS!

( Happy now, RWarden? )

I actually do use MFC a lot, because I know it, and it makes certain things to do with Windows User Interfacing a lot easier. For windowed, office-type apps, it''s a godsend, let me tell ya.



If you are programming for Windows only, fine. No problem. But don''t try porting.

This topic is closed to new replies.

Advertisement