Which vector address is safer? - c++

Assuming a function needs a pointer to a vector of type T but when I have only a vector of vector of type T(type is not guaranteed to be a POD), is this
std::vector<std::vector<T>> input;
auto selectedVectorPtr=&input[j];
safer than this
std::vector<std::vector<T>> input;
auto selectedVectorPtr=&(input[j]);
also assuming input's scope doesn't end until that function which takes selectedVectorPtr as parameter.
My concerns(/misconceptions) are:
does () create any temporary object? So is taking address of it is bad?
does operator overloading of & or [] on type T have any effect on changing priority of operator precedence?
what if vector(or both) is resized after getting address?

operator[] has higher precedence then operator& (postfix operators have the highest precedence), so it is evaluated first here, no parenthesis needed. There is no difference between &input[j] and &(input[j]) here.
Alternative simpler syntax:
auto selectedVectorPtr = input.data() + j;
No need for std::addressof here either.

The operator precedence dictates that [] is evaluated before the leading &. Hence, there is no difference in the two expressions.
As you were wondering about the safety implications of the snippets, there are two issues to consider for &input[j] (regardless of the outer parentheses):
The index can be out of bounds, leading to undefined behavior. You might want to use the (possibly throwing but safer) std::vector::at instead of std::vector::operator[] and wrap that into a try-catch block.
If you want to take the address of T, which is unknown a priori, operator & could be overloaded for T. While this is evil in the first place, you can use std::addressof to mitigate the possibility. Note that this is not necessary in your case, as you're taking the address of a std::vector instance.

&input[j] and &(input[j]) will not have any difference. This is because operator[] have higher precedence then that of operator&.
So in both the cases it will evaluate to &(input[j])

Related

operator& that returns an int and operates on 2 vectors?

I would like to define an & operator between two std::vector<int>. This operator should bit-wise and each element of both vectors together and return the number of non-zero components of the resulting vector.
However, if I define int operator&(const std::vector<int> &lhs, const std::vector<int> &rhs), it the compiler doesn't like it and requires operator& to return a boolean. Is this actually a restriction with operator&?
I would like to define an & operator between two std::vector<int>.
You may not (at least not globally; it can in theory be done in a custom namespace but I recommend against it). Operator overloads for standard templates with no user defined type arguments are reserved to the standard library.
I recommend writing a regular function instead.
Any idea why there's that restriction?
Because this restriction allows the standard library to change and add any operator overload that the committee wishes without breaking previously well defined programs that have their own conflicting overloads (by virtue of not allowing such overloads to be defined).
operator& to return a boolean. Is this actually a restriction with operator&?
No. This is actually not a restriction of binary operator&. It may return int.

What is the difference between these two parameters in C++?

I am new to C++ and currently am learning about templates and iterators.
I saw some code implementing custom iterators and I'm curious to know what the difference between these two iterator parameters is:
iterator & operator=(iterator i) { ... i.someVar }
bool operator==(const iterator & i) { ... i.someVar }
They implement the = and == operators for the particular iterator. Assuming the iterator class has a member variable 'someVar', why is one operator implemented using "iterator i" and another with "iterator & i"? Is there any difference between the two "i.someVar" expressions?
I googled a little and found this question
Address of array - difference between having an ampersand and no ampersand
to which the answer was "the array is converted to a pointer and its value is the address of the first thing in the array." I'm not sure this is related, but it seems like the only valid explanation I could find.
Thank you!
operator= takes its argument by value (a.k.a. by copy). operator == takes its argument by const reference (a.k.a. by address, albeit with a guarantee that the object will not be modified).
An iterator may be/contain a pointer into an array but it is not itself an array.
The ampersand (&) has different contextual meanings. Used in an expression, it behaves as an operator. Used in a declaration such as iterator & i, it forms part of the type iterator & and indicates that i is a reference, as opposed to an object.
For more discussion (with pictures!), see Pass by Reference / Value in C++ and What's the difference between passing by reference vs. passing by value? (this one is language agnostic).
the assignment operator = takes the iterator i as value, which means a copy of the original iterator is made and passed to the function so any changes applied to the iterator i inside the operator method won't affect the original.
the comparison operator == takes a constant reference, which denotes that the original object can't/shouldn't be changed in the method. This makes sense since a comparison operator usually only compares objects without changing them. The reference allows to pass a reference to the original iterator which lives outside the method. This means that the actual object won't be copied which is usually faster.
First, you don't have an address of an array here.
There's no semantic difference, unless you try to make a local change to the local variable i: iterator i will allow a local change, while const iterator & i will not.
Many people are used to writing const type & var for function parameters because passing by reference can be faster than by value, especially if type is big and expensive to copy, but in your case, an iterator should be small and cheap to copy, so there's no gain from avoiding copying. (Actually, having a local copy can enhance locality of reference and help optimization, so I would just pass small values by value (by copying).)

Combined Operator Overloading in C++?

Is it possible to overload operators in such a way that you can capture a specific combination of them? For example lets say I have a custom object myObject of type MyType where [] is already overloaded to pass such calls down to a map object. That said, in the case of the following code:
int value = myObject["someProp"];
I'm already overloading [] but in this case I'd like to know when [] is being called on the object in an assignment, with a reference to the type of object that the property lookup is to be assigned to. This way I can cast the value coming out of the dynamic property lookup and so on and so forth. Any input is appreciated!
For more insight into exactly what I'm trying to accomplish, see this related question of mine.
No, you can't overload on the return type, or on the context in which the call appears (e.g. in an assignment etc).
You could, however, return a proxy object that would have a bunch of overloaded conversion operators. Without seeing what you intend to do, it's hard to say how far you might be able to get with this approach, or whether it's even a sane thing to do.
If you want type deduction for things like this, your best bet is to overload operator() instead, and pass in the thing you're going to be assigning to as a dummy parameter, i.e.:
MyType myObject;
int value = myObject("someProp", value);
I've made something like this work pretty well in the past. In particular, see e.g.:
https://github.com/sgolodetz/hesperus2/blob/master/source/engine/core/hesp/objects/base/ObjectManager.tpp
In principle, it's rather straightforward to do: all that is needed is
for your operator to return a proxy which then overloads the operators
you want to catch. In practice, it can cause more than a few problems;
readers will expect (a op1 b) op2 c to have
the same semantics as T tmp(a ip1 b); tmp op2
c. There are some common exceptions, however:
The operator[] in a multi-dimensional array will often return a
proxy which defines an operator[] itself, in order to support [][]
correctly.
More generally, a container which for whatever reasons needs to know
when a value is modified will have an operator[] which returns a
proxy; within the proxy, assignment is defined as setting the value in
the owning container, and there will be a convertion operator to the
value type, for use in rvalue contexts. Of course, this means that
things like m[i][j].funct() don't work; typically, however, this sort
of thing is used for matrices of numeric types, where member functions
aren't that relevant.
In contexts where it is desirable to support overload resolution based
on the target type (your example), the function can return a proxy with
overloaded conversion operators. You want to be extremely careful with
this—overloaded conversion operators are often a recipe for
overload resolution ambiguities&rdash;but there are enough exceptions
that this situation bears mentionning. (Important, here, is that the
results of the operator will amost always be used to intialize or to
assign to a specific object, the type of which determines which
conversion operator will be called.)
BTW: I might mention that in the example you give, there is no
assignment; it is a classical initialization. In this case, defining
the operator[] to return a proxy which defines operator int() const
would do the trick very well. Before going this route, however, you
should very definitely consider all of the use cases of your class, and
ensure that there are none in which the actual target type is ambiguous.
The other answers are basically correct that you can't do it. aix hints at a solution of a custom return type with overloaded conversion operators, but rightly indicates it isn't a sane thing to do. I've ventured down this path quite often and ultimately implicit conversions, and sequences of conversions, and ambiguities will bite you in you in the behind.
I've had a need of this quite often though. Ultimately I end up going for a series of overloaded functions, or templates, depending on your needs, perhaps like this:
void lookup( int& v, char const * name );
void lookup( double& c, char const * name );
In the template case I created global converters and did the below member function:
template<T>
void lookup( T&v, char const* name ) { v = convert<T>( get(name) ); }
If you want to keep the return value as the lookup you'll have to explicitly call a templated function.
template<T> T get( char const * name ) { ... }
//use
int a = obj.get<int>( "name" );
double b = obj.get<double>( "floaty" );
No, you can't do that.
Moreso, madness that way lies!

Do I have to return a reference to the object when overloading a pre-increment operator?

Can I use:
MyClass& MyClass::operator++ () {
a++; // private var of MyClass
return (*this);
}
Or it can be:
MyClass MyClass::operator++ ();
What's the difference?
Thanks for answers. I have another issue.
Many people do something like that:
MyClass& MyClass::operator++();
MyClass MyClass::operator++(int);
Isn't it illogical? Please give some examples if you can.
I know that the first version is pre-increment and the second is post-increment, but i ask why the first one returns reference but the second one not? It is in the same code (class), and the same use of the code.
No, you don't have to return the reference to your object when you overload the pre-increment operator. In fact you may return anything you'd like, MyClass, int, void, whatever.
This is a design issue -- you must ask yourself what is the most useful thing to the users of your class that you are able to return.
As a general rule, class operators are the most useful when they cause the least confusion, that is, when they operate the most like operators on basic types. In this case, the pre-increment operator on a basic type:
int i = 7;
j = ++i;
increments the variable and then returns the new value. If this is the only use you want MyClass to have, then returning a copy of your class is sufficient.
But, the pre-increment operator on a basic type actually returns an lvalue. So, this is legal:
int i = 7;
int *p = &++i;
If you want to support an operation like this, you must return a reference.
Is there a specific reason that you don't want to return a reference? Is that not a well-formed concept for your particular class? If so, consider returning void. In that case, this expression: ++myObject is legal, while this myOtherObject = ++myObject is not.
You can return whatever you want. void, reference to self, copy of self, something else. Whichever you prefer (or need).
If you plan using the ++ operator in chained expressions (like (++obj).something()) then return a reference. In you don't, then void is just fine.
Remember that in the end, operators are just like normal methods: you can do whatever you want with them, provided you respect their prototype.
For question two:
Prefix returns a reference, as expected.
Postfix returns a copy to be consistent with the behavior of the postfix operator(s).
Break it down simply to int:
int c = 0;
if(++c)
{
// true, prefix increments prior to the test
}
c = 0;
if(c++)
{
// false, c now == 1, but was incremented after the test
}
Implementing this behavior in a class requires a copy be returned because the postfix operator will have modified the state of the object.
If the program does not need true postfix operation, you are free of course to implement how you wish. While there are standard ways of writing these operators (that are understood by most C++ programmers), there's nothing actually stopping you from implementing this in different ways.
The argument provided about incorrect functionality surrounding (obj++)++ is not really important, as that code won't even compile for POD types (in Visual Studio 2010, at least), because for POD types, a copy is returned and that temporary copy cannot be used alone as an l-value.
However, for the prefix operator a reference is the preferred return as that allows the proper behavior for chaining the operation (++(++obj)).
Its not compulsory, but we should try to make operator overloading intuitive and it should work as per the operator which is being overloaded.
If we do
int i = 10;
i++ = 0
Then second statement is not allowed it says it requires lvalue as i++ denotes older state of i not a storage ...
while ++i = 0 perfectly works fine ..
so just to keep it in sync with actual operators prefix version had to return refence so that its return value may be treated as lvalue in expressions.
Yes, you should return by reference. No need for the parenthesis around *this.
EDIT: Replying to your comment... You don't have to return by reference. But in general we follow some guidelines which make our classes behave "as expected" when compared to the builtin semantics of such operators. You might wanna take a look at http://www.parashift.com/c++-faq-lite/operator-overloading.html.

Clarification on Operators

I've been reading up on class operators and came across the following example:
class Array {
public:
int& operator[] (unsigned i) { if (i > 99) error(); return data[i]; }
private:
int data[100];
};
Does this mean I can replace [ and ] with whatever I want? For example, could I use parentheses?
Also, what is the significance of the ampersand in int& operator[]?
On a slightly less important note, would it be syntactically correct to use int& operator [] instead of int& operator[]?
Does this mean I can replace [ and ] with whatever I want?
Nopes! Not all operators can be overloaded.
For example, could I use parentheses?
You can but you shouldn't.
Also, what is the significance of the ampersand in int& operator[]?
It means you are returning a reference to an int variable.
EDIT: On a slightly less important note, would it be syntactically correct to use int& operator [] instead of int& operator[]?
There is no difference between the two.
What you are doing is defining an Array class that wrapes a simple integer array. By overloading the [] operator you can acces each element of the array as with any other array, the advantage here is that your are checking superior limit to avoid buffer overflow. The ampersand means that you are returning a reference to the array element, it allows you both assigment a value and getting a value. In c++ when you overload the [] operator dont forget both const and non-const versions:
int& operator[] (conts int a) {...}
int operator[] (conts int a) {...} const
You could use parentheses, because there also is an
operator()
and some libraries (eg. boost::blas) do this. BUT: You cannot make up new parenthesis, because there is no operator{} or operator<>
RE your syntax question: Haven't tried, but don't think so, because operator[] is the name of a function, and you shouldn't add whitespace to a function name.
While you can mostly define operators as you like, parens would be a problem. The reason is conflict with the classes constructor! Array(25), what does it mean? I'm not sure if this is allowed (though I'm quite sure someone else will know), but the point is that even if you are allowed you are going to have a problem with doing that.
In general - symbols that serve as operators can be overloaded/redefined You can specify how ==, &, > and [] work for your class. You can't decide the letter 'q' now means some type of comparison. As far as the () issue, im not sure.
The reference mark & is necessary for indexing because you want to potentially do assignment on the address returned, not just got a value. If you permit the lax description, the "majority' of your operators will not require this.
1) NO there is a fixed set of available 'overloadable' operators in C++.
See this table in wikipedia:
http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Table
There is an 'Overloadable' Column in each table
2) The int& indicates that you're returning a Reference to the value.
References in C++ are similar to pointers and worth their own discussion, but in the case of the operator here what it allows if for you to use this operator as the left hand operand of an assignment e.g.
x[3] = 0;
This wouldn't work if it just returned an int;