Semantics of default semantics in C ++

EDIT: This question is more about language engineering than C ++ itself. I used C ++ as an example to show what I wanted, mainly because I use it daily. I did not want to know how this works in C ++, but open a discussion on how this can be done.

This is not how it works right now, the way I would like it to be possible, and that would probably break the C compilation, but what I think is the "C" extern.

I mean, in every function or method that you declare right now, you must explicitly write that the object will be sent by a link prefixed to it by the reference operator. I wish that every non-POD type was automatically sent by reference, because I use it a lot, in fact for every object larger than 32 bits, and that almost every class of mine.

Let's demonstrate how this is happening right now, suppose a, b and c are classes:

 class example {
     public:
         int just_use_a (const a & object);
         int use_and_mess_with_b (b & object);
         void do_nothing_on_c (c object);
 };

Now what I want:

 class example {
     public:
         int just_use_a (const a object);
         int use_and_mess_with_b (b object);
         extern "C" void do_nothing_on_c (c object);
 };

Now do_nothing_on_c () can behave just like today.

It would be interesting, at least for me, it feels much clearer, and also if you know that each non-POD parameter comes by reference, I think the errors will be the same if you had to declare it explicitly.

Another point of view for this change, from someone from C, the reference operator, seems to me a way to get the address of the variable that I used to get pointers. I mean, this is the same operator, but with different semantics in different contexts, isn't that too bad for you?

+7
c ++ syntax programming-languages semantics
source share
9 answers

I assume that you are missing the C ++ point and C ++ semantics. You missed the fact. C ++ correctly passes (almost) everything by value because it is the way it is done in C. Always . But not only in C, as I show you below ...

Parameters Semantics in C

In C, everything is passed by value. "primitives" and "POD" are transmitted by copying their values. Change them in your function and the original will not be changed. However, the cost of copying some PODs may not be trivial.

When you use pointer notation (*), you are not following the link. You transmit a copy of the address. Which is more or less the same, but with one subtle difference:

typedef struct { int value ; } P ; /* p is a pointer to P */ void doSomethingElse(P * p) { p->value = 32 ; p = malloc(sizeof(P)) ; /* Don't bother with the leak */ p->value = 45 ; } void doSomething() { P * p = malloc(sizeof(P)) ; p->value = 25 ; doSomethingElse(p) ; int i = p->value ; /* Value of p ? 25 ? 32 ? 42 ? */ } 

The final value of p-> is 32. Because p was passed by copying the address value. So the original p was not changed (and the new one was leaked).

Parameters Semantics in Java and C Sharp

This may be surprising to some, but in Java everything is also copied by value. The above C example will give exactly the same results in Java. This is almost what you want, but you won’t be able to pass a "by reference / pointer" primitive as easily as in C.

In C #, they added the ref keyword. It works more or less like a link in C ++. The fact is that in C # you have to mention this both in the function declaration, and with every call. I think this is not what you want.

Parameters Semantics in C ++

In C ++, almost everything is passed by copying the value. When you use nothing but a character type, you copy the character (as is done in C). That is why when you use *, you pass a copy of the address of the character.

But when you use &, then suppose you are passing a real object (be it struct, int, pointer, whatever): Link.

This is easily perceived as syntactic sugar (i.e., behind the scenes, it works like a pointer, and the generated code is the same as for the pointer). But...

The truth is that a link is more than syntactic sugar.

  • Unlike pointers, it allows you to manipulate an object as if it were on the stack.
  • Separate pointers, if they are associated with the const keyword, it allows implicit progression from one type to another (via constructors, mainly).
  • Unlike pointers, a character must not be NULL / invalid.
  • Unlike "copies", you do not waste time copying an object
  • Unlike by-copy, you can use it as a parameter [out]
  • Unlike by-copy, you can use the full range of OOP in C ++ (that is, you pass the complete object to a function that expects an interface).

So links have the best of both worlds.

Let's look at a C example, but with a C ++ version in the doSomethingElse function:

 struct P { int value ; } ; // p is a reference to a pointer to P void doSomethingElse(P * & p) { p->value = 32 ; p = (P *) malloc(sizeof(P)) ; // Don't bother with the leak p->value = 45 ; } void doSomething() { P * p = (P *) malloc(sizeof(P)) ; p->value = 25 ; doSomethingElse(p) ; int i = p->value ; // Value of p ? 25 ? 32 ? 42 ? } 

The result is 42, and the old p leaked, replaced by the new p. Since, unlike C code, we do not pass a copy of the pointer, but a link to a pointer, that is, a pointer.

When working with C ++, the above example should be clear. If this is not the case, then you are missing something.

Conclusion

C ++ is the value of pass-by-copy / value, because that's how everything works, whether in C, in C # or in Java (even in JavaScript ...: -p ...). And, like C #, C ++ has a reference operator / keyword as a bonus .

Now, as I understand it, you are probably doing what I call semi-jockingly C + , that is, C with some limited C ++ features.

Perhaps your solution uses typedefs (it will amaze your C ++ colleagues, though, to see that the code is dirty with useless typedefs ...), but it will only confuse the fact that you are really absent in C ++.

As another post says, you have to change your mindset from developing C (whatever) to developing in C ++, otherwise you should switch to another language. But do not continue to program the C function with C ++ functions, because deliberately ignoring / obfuscating the power of the idioms you use, you will create suboptimal code.

Note. And do not go with a copy of anything but the primitives. You will drop your function from your OO capacity, but in C ++ this is not what you want.

Edit

The question has been slightly modified (see https://stackoverflow.com/revisions/146271/list ). I gave my initial answer and will answer new questions below.

What do you think of the default semantics in C ++? As you said, this will break compatibility, and you will have a different path for primitives (i.e., built-in types that will still be passed by copy) and structs / objects (which will be passed as links). You would need to add another operator to the "pass-by-value" value (extern "C" is pretty awful and already used for something completely different). No, I really like how it is done today in C ++.

[...] the reference operator seems to me a way to get the address of the variable that I used to get the pointers. I mean, this is the same operator, but with different semantics in different contexts, isn't that too bad for you? Yes and no. The operator → changed its semantics when used with C ++ streams. Then you can use the + = operator to replace strcat. I assume that the operator is also used because its value is “opposite to the pointer” and because they did not want to use one more character (ASCII is limited, and the scope operator :: as well as the pointer → shows that several other characters can be used ) But now, if it bothers you, && will really annoy you, because they added the unary && to C ++ 0x (kind of super-link ...). I have yet to digest it ...

+15
source share

A compiler option that completely changes the meaning of a section of code sounds like a really bad idea to me. Either use C ++ syntax or find another language.

+10
source share

I will no longer abuse links by making each (unskilled) parameter a link.

The main links to links were added in C ++: to support operator overloading ; if you need pass-by-reference semantics, C had a perfectly reasonable way to do this: pointers.

Using pointers clearly shows your intention to change the value of a pointed object, and this can be seen simply by looking at the function call, you do not need to look for the function declaration to see if it uses a link.

Also see

I want to change the argument, should I use a pointer or use a link? I do not know a strong logical reason. If you pass `` not an object '' (for example, a null pointer) is acceptable, using a pointer makes sense. My personal style is to use a pointer when I want to change because in some contexts it makes it easier to identify that a modification is possible.

of the same frequently asked questions .

+2
source share

Honestly, I think that all this transmission, passed on the idea of ​​comparison in C ++, is misleading. Everything passes by value. You have three cases:

  • Where do you pass the local copy of the variable

     void myFunct(int cantChangeMyValue) 
  • Where do you pass the local copy of the variable pointer

     void myFunct(int* cantChangeMyAddress) { *cantChangeMyAddress = 10; } 
  • Where you pass the link, but through the magic of the compiler, it's exactly the same as if you passed the pointer and just dereferenced it every time.

     void myFunct(int & hereBeMagic) { hereBeMagic = 10; // same as 2, without the dereference } 

It seems to me personally that he is less confused to remember that everything passes by value. In some cases, this value may be an address that allows things to be changed outside the function.

What you offer will not allow the programmer to make number 1. I personally think that it would be a bad idea to take this option away. One of the main advantages of C / C ++ is fine-grained memory. Everything that is passed by reference is simply trying to make C ++ more like Java.

+1
source share

Yes, I find this a rather confusing overload.

This is what Microsoft has to say about the situation:

Do not confuse link ads with the address of the operator. When an identifier is preceded by a type, for example, int or char, then the identifier is declared as a reference to the type. When the identifier is not preceded by a type, it is used as the address of the operator.

I'm not very good in C or C ++, but I have big headaches that sort different uses * and in both languages ​​than I code in assembler.

+1
source share

The best advice is to make a habit of thinking about what you really want. Passing by reference is good when you do not have a copy constructor (or you do not want to use it), and it is cheaper for large objects. However, after this mutations to the parameter are felt outside the class. Instead, you can pass a const reference - then there are no mutations, but you cannot make local changes. Skip const by value for cheap objects that should be read-only in functions and pass non-constant by value when you want to get a copy that you can make local changes to.

Each permutation (by-value / by-reference and const / non-const) has important differences that are definitely not equivalent.

+1
source share

When you pass by value, you copy data onto the stack. If you have an = operator specific to the structure or class that you are passing, it is executed. There is no compiler directive that I know of that would remove the impasse of implicit language confusion that inherently caused the proposed change.

It is common practice to pass values ​​by const reference, not just by reference. This ensures that the value cannot be changed in the calling function. This is one element of a constant code base.

The completely const-correct code base goes even further by adding const to the end of the prototypes. Consider:

 void Foo::PrintStats( void ) const { /* Cannot modify Foo member variables */ } void Foo::ChangeStats( void ) { /* Can modify foo member variables */ } 

If you must pass the Foo object to a function with the const prefix, you can call PrintStats (). The compiler made a mistake when calling ChangeStats ().

 void ManipulateFoo( const Foo &foo ) { foo.PrintStats(); // Works foo.ChangeStats(); // Oops; compile error } 
+1
source share

there is something incomprehensible. when you speak:

int b (b & param);

what did you intend for the second "b"? did you forget to type in? did you forget to write differently about the first b? don't you think that something like:

 class B{/*something...*/}; int b(B& param); 

Since then, I suppose you mean what I write.

Now, your question is: "Don't you think it is better if the compiler considers each pass by non-POD value as pass-by-ref?" The first problem is that it will violate your contract. I suppose you mean the missing CONST link, not just the link.

Now your question boils down to the following: "Do you know if there is any compiler directive that can optimize a function call by value?"

Now the answer is "I do not know."

0
source share

I think C ++ gets very dirty if you start mixing all the available parameters with their const variations.

It quickly gets out of hand to trace all calls to copy constructors, all overloaded types, etc.

0
source share

All Articles