This question already has answers here:
Default constructor with empty brackets
(9 answers)
Closed 7 years ago.
Can you figure out what is wrong with the statement below?
GCC error states:
'type name' declared as function returning array
#define MACRO(a) (a)[1]
class index {
public:
typedef int index_type[2];
const index_type& operator[](int i) const;
};
int k = 0;
int i = MACRO(index()[k]);
btw: I know what is wrong, I thought it was amusing thing to share. Many thanks to litb, his explanation of previous gotcha helped to solve this error pretty quickly.
In the expanded line:
int i = (index()[k])[1];
(index()[k]) is interpreted as a cast expression, declaring a function that returns an array of length k of index. At least, that's what it looks like is happening. How gcc is manages to validly interpret the [1] as an expression, I'm not sure.
My guess would be there's an ambiguity in your syntax. The compiler might be looking at the expanded macro:
int i = (index()[k])[1];
And thinking that index is actually a non-member function declaration that returns an array, rather than construction of a temporary object of type index.
But that's just a guess... if you know the answer already, please enlighten us :)
When you apply your macro, it expands to:
class index
{
// ...
typedef int index_type[2];
const index_type& operator[](int i)const;
// ...
};
int k = 0;
int i = (index()[k])[1];
Now the problem (assuming that index::operator[] is public, and it is non-obvious from your code snippet that it is) is that the result of index::operator[] is returned by reference, and you are constructing the index() object as a temporary, and so, assuming your index::operator[] is implemented how I'm guessing you've implemented it (returning a reference to a member object), the result of index::operator[] will be invalid immediately after it is returned (as the temporary is destructed), and so you have undefined behavior.
Related
This question already has answers here:
What are the use cases for having a function return by const value for non-builtin type?
(4 answers)
Closed 8 years ago.
What is the purpose of the const in this?
const Object myFunc(){
return myObject;
}
I've just started reading Effective C++ and Item 3 advocates this and a Google search picks up similar suggestions but also counterexamples. I can't see how using const here would ever be preferable. Assuming a return by value is desirable, I don't see any reason to protect the returned value. The example given for why this might be helpful is preventing unintended bool casts of the return value. The actual problem then is that implicit bool casts should be prevented with the explicit keyword.
Using const here prevents using temporary objects without assignment. So I couldn't perform arithmetic expressions with those objects. It doesn't seem like there's ever a case that an unnamed const is useful.
What is gained by using const here and when would it be preferable?
EDIT: Change arithmetic example to any function that modifies an object that you might want to perform before an assignment.
In the hypothetical situation where you could perform a potentially expensive non-const operation on an object, returning by const-value prevents you from accidentally calling this operation on a temporary. Imagine that + returned a non-const value, and you could write:
(a + b).expensive();
In the age of C++11, however, it is strongly advised to return values as non-const so that you can take full advantage of rvalue references, which only make sense on non-constant rvalues.
In summary, there is a rationale for this practice, but it is essentially obsolete.
It's pretty pointless to return a const value from a function.
It's difficult to get it to have any effect on your code:
const int foo() {
return 3;
}
int main() {
int x = foo(); // copies happily
x = 4;
}
and:
const int foo() {
return 3;
}
int main() {
foo() = 4; // not valid anyway for built-in types
}
// error: lvalue required as left operand of assignment
Though you can notice if the return type is a user-defined type:
struct T {};
const T foo() {
return T();
}
int main() {
foo() = T();
}
// error: passing ‘const T’ as ‘this’ argument of ‘T& T::operator=(const T&)’ discards qualifiers
it's questionable whether this is of any benefit to anyone.
Returning a reference is different, but unless Object is some template parameter, you're not doing that.
It makes sure that the returned object (which is an RValue at that point) can't be modified. This makes sure the user can't do thinks like this:
myFunc() = Object(...);
That would work nicely if myFunc returned by reference, but is almost certainly a bug when returned by value (and probably won't be caught by the compiler). Of course in C++11 with its rvalues this convention doesn't make as much sense as it did earlier, since a const object can't be moved from, so this can have pretty heavy effects on performance.
It could be used as a wrapper function for returning a reference to a private constant data type. For example in a linked list you have the constants tail and head, and if you want to determine if a node is a tail or head node, then you can compare it with the value returned by that function.
Though any optimizer would most likely optimize it out anyway...
This question already has answers here:
What are the use cases for having a function return by const value for non-builtin type?
(4 answers)
Closed 8 years ago.
What is the purpose of the const in this?
const Object myFunc(){
return myObject;
}
I've just started reading Effective C++ and Item 3 advocates this and a Google search picks up similar suggestions but also counterexamples. I can't see how using const here would ever be preferable. Assuming a return by value is desirable, I don't see any reason to protect the returned value. The example given for why this might be helpful is preventing unintended bool casts of the return value. The actual problem then is that implicit bool casts should be prevented with the explicit keyword.
Using const here prevents using temporary objects without assignment. So I couldn't perform arithmetic expressions with those objects. It doesn't seem like there's ever a case that an unnamed const is useful.
What is gained by using const here and when would it be preferable?
EDIT: Change arithmetic example to any function that modifies an object that you might want to perform before an assignment.
In the hypothetical situation where you could perform a potentially expensive non-const operation on an object, returning by const-value prevents you from accidentally calling this operation on a temporary. Imagine that + returned a non-const value, and you could write:
(a + b).expensive();
In the age of C++11, however, it is strongly advised to return values as non-const so that you can take full advantage of rvalue references, which only make sense on non-constant rvalues.
In summary, there is a rationale for this practice, but it is essentially obsolete.
It's pretty pointless to return a const value from a function.
It's difficult to get it to have any effect on your code:
const int foo() {
return 3;
}
int main() {
int x = foo(); // copies happily
x = 4;
}
and:
const int foo() {
return 3;
}
int main() {
foo() = 4; // not valid anyway for built-in types
}
// error: lvalue required as left operand of assignment
Though you can notice if the return type is a user-defined type:
struct T {};
const T foo() {
return T();
}
int main() {
foo() = T();
}
// error: passing ‘const T’ as ‘this’ argument of ‘T& T::operator=(const T&)’ discards qualifiers
it's questionable whether this is of any benefit to anyone.
Returning a reference is different, but unless Object is some template parameter, you're not doing that.
It makes sure that the returned object (which is an RValue at that point) can't be modified. This makes sure the user can't do thinks like this:
myFunc() = Object(...);
That would work nicely if myFunc returned by reference, but is almost certainly a bug when returned by value (and probably won't be caught by the compiler). Of course in C++11 with its rvalues this convention doesn't make as much sense as it did earlier, since a const object can't be moved from, so this can have pretty heavy effects on performance.
It could be used as a wrapper function for returning a reference to a private constant data type. For example in a linked list you have the constants tail and head, and if you want to determine if a node is a tail or head node, then you can compare it with the value returned by that function.
Though any optimizer would most likely optimize it out anyway...
This question already has answers here:
Use of 'const' for function parameters
(31 answers)
Closed 7 years ago.
I was reading my C++ book (Deitel) when I came across a function to calculate the volume of a cube. The code is the following:
double cube (const double side){
return side * side * side;
}
The explanation for using the "const" qualifier was this one: "The const qualified should be used to enforce the principle of least privilege, telling the compiler that the function does not modify variable side".
My question: isn't the use of "const" redundant/unnecessary here since the variable is being passed by value, so the function can't modify it anyway?
The const qualifier prevents code inside the function from modifying the parameter itself. When a function is larger than trivial size, such an assurance helps you to quickly read and understand a function. If you know that the value of side won't change, then you don't have to worry about keeping track of its value over time as you read. Under some circumstances, this might even help the compiler generate better code.
A non-trivial number of people do this as a matter of course, considering it generally good style.
You can do something like this:
int f(int x)
{
x = 3; //with "const int x" it would be forbidden
// now x doesn't have initial value
// which can be misleading in big functions
}
Note: I am using the g++ compiler (which is I hear is pretty good and supposed to be pretty close to the standard).
Not trying to start a grammar war, but just a random question... What is the ideal way to declare a pointer?
int* pI = 4;
int *pI = 4;
(or my favorite, I know it's non-pretty, but I like it):
int*pI = 4;
Same question stands for references:
int& rI = 4;
int &rI = 4;
or
int&rI = 4;
Maybe there is no right answer. Similarly, should I care whether a constant integer is declared as:
const int I = 4;
or
int const I = 4;
I'm fine with not caring...
I do like the way a const function is declared by having a const after the last parenthesis.
And I believe a constant function has a distinct function signature than the similar non-const function (i.e. the const-nesss is part of the function signature, unlike most sources that say it just depends on the arguments type and the return type).
Is this right? Should I care?
I prefer
int* a;
int& b;
for the following reason: the type is int* and not int. For me - the type belongs together and needs to stand separate from the name. I know this introduces some problems with
int* a, b;
but that's why I don't declare to variables in one line.
Other than that - like VJo said: stick to the coding standard. If everyone around you does it one way, don't do it the other.
Coding standards might tell you how to declare or define your variables.
Other then that, use whatever suits you better.
And I believe a constant function has a distinct function signature than the similar non-const function (i.e. the const-nesss is part of the function signature, unlike most sources that say it just depends on the arguments type and the return type).
A constant function has a keyword const which is appended at the end of it.
int doSomething() const;
It means that the function will not alter the state(members) of the class.
Mentioning const on an argument implies that the function will not alter the state of that variable(param in below example) being passed to the function.
int doSomething(const int param);
Mentioning const before the return type applies to the type being returned by the function.
const int doSomething();
Implies the function returns a const integer value.
So yes your understanding is correct. And there is no other way to declare a function const except putting a const after the last paranthesis.
Also, note that const member function can be only called on a const object, while a non const member function can be called by const as well as non const objects of that class.
As far as the way of declaring, Each organization have their own coding guidelines and you should stick to that, Yes there is no distinct advantage of using those contructs you mentioned in either way with respect to compiler optimization or treatment. Just follow what you like or what your organzation wants you to follow.
Bjarne Stroustrup uses:
int* a;
so, that's good enough for me.
Hi I was stumbling through legacy code, and I came across a wierd method definition/declaration. I have an educated guess of what it does, but I cannot be 100% sure yet.
declaration:
const SomeEnumeratedId (&SomeMethod() const)[SOME_CONSTANT_VALUE];
definition
const SomeEnumeratedId (&SomeClass::SomeMethod() const)[SOME_CONSTANT_VALUE]
{
return someMemberArray;
}
My best guess is that it is passing a reference to someMemberArray and that it is guaranteeing that it is of size SOME_CONSTANT_VALUE, but I have never seen the [] notation after the method declaration as it appears, and there are so many parentheses.
Any help greatly appreciated.
It's the declaration of a const member function taking no parameters and returning a reference to an array of SOME_CONSTANT_VALUE const SomeEnumeratedIds.
It looks easier to understand with a typedef.
typedef const SomeEnumeratedId SomeArrayType[SOME_CONSTANT_VALUE];
SomeArrayType& SomeClass::SomeMethod() const
{
return someMemberArray;
}
That weird notation, as #Charles has already pointed out is the declaration/definition of a constant method that returns a reference to an array of elements stored as a member.
The syntax is quite bizarre and could (and should probably) be simplified by means of a typedef:
typedef SomeEnumerated array_t[SOME_CONSTANT_VALUE];
const array_t& SomeMethod() const;
Yea, it's a consequence of C's utterly backwards type declaration syntax. It's similar to how, when doing an array typedef, you write this: typedef int myArrayType[3];, with the [3] after the new typename, not the original.
If you're really clever you can use {std,tr1,boost}::array -- worth considering anyway -- so that you end up with:
array<SomeEnumeratedId, SOME_CONSTANT_VALUE>& SomeClass::SomeMethod() const;
instead.
The workarounds with typedefs (explored in other answers) are related, although not quite equivalent as {std,tr1,boost}::array are wrappers, not just typedefs.