I am writting a method returning a double*. However, I would like to base another method behavior on output from this method. I would like to have
if (methodReturningArray()==0)
{
this_behavior();
}
else
{
this_other_behavior(methodReturningArray());
}
Is it appropriate then to have methodReturningArray() returning either the 'initialized' or 'build' double* and if this double* could not be appropriately be initialized or build, returning like that
double* new_array ;
return new_array ;
?
In other words, the double* output plays also role of a boolean to check whether some property is completed so that the double* output can be built.
Thanks and regards.
To indicate that something that you return by pointer has not been initialized, use return NULL. And check for it with if(double* d = method()) (or in any other fashion you like).
However, this is not your (or my) grandfathers C++ and you should only write something like this, when you absolutely have reason to do so. I would prefer to return either a std::array or std::vector by value wrapped and throw an exception if the behavior that leads to initialization failure is somehow exceptional. If failing to initialize is part of the idea I'd wrap the return value in a boost::optional. But probably I'd write something that takes an OutputIterator to not force any particular container on my client.
Notes on disaster: double* d; return d will leave your client with a pointer that points to random memory. There is no way for her to figure out if has to be deleted[] or if it is valid. Always initialize your pointers.
Code snippets:
// outputiterator
template<typename OutputIterator>
void myFunc(OutputIterator o) {
// fill stuff in
if(someThing) {
for(int i = 0; i < 5; ++i)
{
*o++ = 23;
}
} else {
// leave it empty
}
}
// client calls like:
std::vector<double> v;
myFunc(std::back_inserter(v));
if(!v.empty()) {
} else {
}
// exception
std::vector<double> myFunc() {
std::vector<double> v;
if(someThing) { v.push_back(23); return v; }
else throw std::runtime_error("Nargh!");
}
// client
try {
auto v = myFunc();
} catch(std::runtime_error err) {
}
// optional
boost::optional<std::vector<double>>
myFunc() {
std::vector<double> v;
if(someThing) { v.push_back(23); return v; }
else return boost::optional< std::vector<double> >();
}
//client
auto v = myFunc();
if(v) {
} else {
}
You got three ways, basically.
1) On error, return NULL. Then you can do boolean checks without issue, and it's sufficient in very most of cases.
2) Return boolean, and handle the double* output using a reference or a pointer argument like this:
bool methodReturningArray(double **out) { *out = ...; return true; }
double *out;
if (!methodReturningArray(&out)) this_other_behavior(out); else ....
3) Throw an exception - IMO kinda convoluted and unuseful.
Returning uninitialized pointer won't allow you to do boolean evaluation on it, and it's dangerous, as such pointer will be assumed dangling pointer afterwards.
Related
Please consider this scenario.
I'm creating a function for [] operator as in the std::vector whose inner body is like this:
int temp;
if(argument >= 0 && argument < size) {
return &my_vector[i];
} else {
cout << "out of bounds" << endl;
//i need to return here something but this gives me an error: local variable cannot be returned by reference.
return &temp;
}
where argument is the argument passed to the function. The return type for this function is 'T*'.
I'm looking for both the read and write cases:
vector[100] = 1;
and int answer = vector[100];
That's why they are returned by reference.
What should be returned in the else part?
First of all, you are not returning a reference, but a pointer, which makes the method not very useful. Instead of
vector[100] = 1;
int answer = vector[100];
You would have to write
*vector[100] = 1;
int answer = *vector[100];
To get what you want you should return a reference not a pointer. Ie return type should be T& not T*.
Then you have basically two options. Either you mimic vectors operator[]. It does not do any bounds checking. It is up to the caller to make sure to pass valid indices:
return my_vector[i]; // thats all (assuming my_vector[i] returns a reference)
The other option is to throw an exception as std::vector::at does:
if(i >= 0 && i< size) {
return my_vector[i];
} else {
throw std::out_of_range("invalid index");
}
You cannot return a reference to a local variable, because that reference is dangling as soon as the method returns and the local variables lifetime ended.
You have to choose which approach fits better. std::vector offers both. Typically when the method is called in a loop:
for (size_t i=0; i<size;++i) {
foo[i] = i;
}
You do not want to incur the overhead of checking the index on each access. On the other hand sometimes indices are computed and the caller wants to have the bounds check encapsulated rather than doing it manually:
try {
size_t index = some_function(); // is this a valid index?!?
foo.at(i) = 42; // let at check it
} catch(...) {
//...
}
PS: You typically need two overloads for those accessors, one const and one non-const, returning const T& and T&, respectively.
I want to define s[i] to return 0 if s[0] was never assigned and return a reference to s[i] if s[i] was assigned earlier (to implement a sparse array). The following code does it, but it ends up creating s[i] whenever I try to get its value, because of the semantics of map.
struct svec{
map<int,double> vals;
/*
double operator[](int index){
return (vals.count(index) > 0) ? vals[index] : 0 ;
else return 0;
}
*/
double &operator[](int index){
return vals[index];
}
};
int main(){
svec s;
s[0] = 10;
cout << s[1] << endl;
}
I want the commented code to be used for resolving the expression s[1]. But if I uncomment it, I get an error.
You cannot overload return values, so you'll have to stick with either returning by reference or by value (or by pointer, etc). The problem with returning by reference is that you have to refer to an existing value that lives in memory. This is, of course, fine when the value is in the map. When it's not, you have to create the default value and store it in memory. Then you have to make sure to properly delete it to not leak memory, but also to make sure the user isn't holding references to the values, as it would introduce unexpected behaviour.
Also, you have to consider the fact that the user can change the value you're returning. If you return the same default, then it's possible for the user to change it to another value. Then all subsequent calls would return a reference to the new value. Resetting the default to 0 every time you return it would also be unexpected for all users that are still keeping a reference to it.
You probably could solve this problem in a stable way, but it would probably require much boilerplate code. I would suggest putting the burden on the user in this case.
class SparseVector {
private:
std::unordered_map<int, double> elements;
public:
void set(int index, double value) {
elements[index] = value;
}
double& get(int index, double& optional) {
auto it = elements.find(index);
if (it != elements.end())
return it->second;
else
return optional;
}
double& get(int index) {
auto it = elements.find(index);
if (it != elements.end())
return it->second;
throw std::runtime_error(
"Couldn't find element at index " + std::to_string(index) +
"! Use get(int index, double& optional) if you don't want errors."
);
}
}
int main() {
double default_value = 0.0;
SparseVector vector;
std::cout << vector.get(0, default_value) << std::endl;
}
I have the following code:
EdgeSet Graph::GetNodeOutcomingEdges(long long NodeId) {
//NodeEdgeMap is an unordereded_map
NodeEdgeMap::iterator it = NodeOutcomingEdges.find(NodeId);
if (it != NodeOutcomingEdges.end()) {
return *(*(it)).second;
}
return EdgeSet();
}
and then..
EdgeSet& OutcomingEdges = RoadGraph.GetNodeOutcomingEdges(Expandee.GetId());
Because the value does not have to be in the map, I have to somehow account for it, under ideal circumstances, return an empty (new) EdgeSet. I could throw and exception, but is it necessary? This compiles fine under VS (probably already accounts for RVO), but not so with g++.
EdgeSet& Graph::GetNodeOutcomingEdges(long long NodeId) {
//NodeEdgeMap is an unordereded_map
NodeEdgeMap::iterator it = NodeOutcomingEdges.find(NodeId);
if (it != NodeOutcomingEdges.end()) {
return *(*(it)).second;
}
static EdgeSet emptySet;
return emptySet;
}
This is just a possible way of doing it: within your Graph class, define an empty member variable of type EdgeSet, with some attribute that identifies it as empty, such as an "mEmptyFlag" boolean:
class Graph {
...
static EdgeSet mEmptyNode(params defining empty node here);
...
}
EdgeSet Graph::GetNodeOutcomingEdges(long long NodeId) {
//NodeEdgeMap is an unordereded_map
NodeEdgeMap::iterator it = NodeOutcomingEdges.find(NodeId);
if (it != NodeOutcomingEdges.end()) {
return *(*(it)).second;
}
return Graph::mEmptyNode;
}
callerFunct {
EdgeSet& OutcomingEdges = RoadGraph.GetNodeOutcomingEdges(Expandee.GetId());
if (OutcomingEdges.mEmptyflag==true) {
deal with empty node here
} else {
....
}
}
Or even better for encapsulation, hide mEmptyFlag and provide an "IsEmpty()" function for EdgeSet.
Assuming you actually want to return a reference, to allow the caller to modify the returned object, you could return a pointer to the found object, or a null pointer if it's not found:
EdgeSet* Graph::GetNodeOutcomingEdges(long long NodeId) {
//NodeEdgeMap is an unordereded_map
NodeEdgeMap::iterator it = NodeOutcomingEdges.find(NodeId);
if (it != NodeOutcomingEdges.end()) {
return it->second;
}
return 0;
}
Alternatively, return a boost::optional<EdgeSet&> which can be empty.
But you should not return a reference "just because", you should return a reference if you want the caller to be able to refer to the same object as is stored in the map, and also be able to modify it. Otherwise, returning a copy, or maybe a const-reference, would be better.
NodeEdgeMap::iterator Graph::GetNodeOutcomingEdges(long long NodeId) {
return NodeOutcomingEdges.find(NodeId);
}
I keep on receiving odd unexpected values for my bool testValue. I keep receiving random numbers as I believe it is trying to access another region of memory. I predict it is how my code is setup within my testNumber() function, but I am unsure of how to solve it. This is my logic.
I have set ok to true. Now I assign the memory address of ok to pOk.
void TextBox::lengthTest(bool *pOk, int length) {
bool ok;
if (length < MAX_LENGTH) {
ok = true;
pOk = &ok;
} else {
ok = false;
pOk = &ok;
}
}
bool lengthTestBool = lengthTest(*pOk, length);
cout << lengthTestBool <<;
output:
85
You have a fundamental misunderstanding of how one uses pointers to implement reference semantics. You want to change thing that is pointed to by the pointer:
*pOK = ok;
However, C++ actually supports references semantics natively through reference types, which may be preferable:
void testNumber(bool & OK, int n)
{
OK = true;
// ...
}
Even better, though, is to simply return a bool:
bool testNumber(int n) { /* ... */ }
if (testNumber(x)) //... etc.
CODE:
vector<DWORD> get_running_proc_list()
{
DWORD proc_list[1024], size;
if(!EnumProcesses(proc_list, sizeof(proc_list), &size))
{
return 0; // PROBLEM HERE!!
}
vector<DWORD> _procs(proc_list, proc_list + size/sizeof(DWORD));
return _procs;
}
ERROR:
cannot convert from 'int' to 'const std::vector<_Ty>'
What is the best possible way to fix this error?
Is there a better way than just returning an empty vector?
Well, your function returns vector, not DWORD. Can't you return just an empty vector:
return std::vector< DWORD >();
or
return std::vector< DWORD >( 1, 0 );
If you really need the 0?
EDIT:
There's another option, if empty vector is not a solution (in case, that it's some kind of valid value and you need to know) - use exception. You can make your own class for exception or use some standard one. So, you can do it like this:
if(!EnumProcesses(proc_list, sizeof(proc_list), &size))
{
throw MyException( "some message, if you want" );
}
I'd advice, if you choose this option, to inherit std::exception.
Or, you can return pointer to std::vector and return NULL in this case. But I would not recommend this. But it's just my opinion.
Throw an exception. That's what they're for. After all, there definitely should be a list of processes that are running.
And definitely do not fail to return by value or something. In this case, the RVO/NRVO is trivially applied. I mean, at worst, you could swaptimize.
Edit: (after reading edited version of question)
Alternatives:
You can make your function to return void and pass to it a vector by reference (or by pointer) then fill the vector in function body.
You can make your function to return boost::shared_ptr<vector<DWORD> > (or some other smart pointer), construct and fill the vector in function body (of course in dynamic memory), then return it's address or NULL.
Throw an exception if above solutions are not suitable.
if(!EnumProcesses(proc_list, sizeof(proc_list), &size))
{
vector<DWORD> empty;
return empty; <--- 0 sized vector
}
You can return an empty vector<>.
As a side note, I would not recommend to return vector by value. Instead pass the vector<> as parameter to be assured that unnecessary copies will not happen.
void get_running_proc_list(vector<DWORD> &_procs) pass by reference and populate
{
...
}
Replace
return 0; // PROBLEM HERE!!
with
return vector<DWORD>(); // NO PROBLEM!!
How about a boost::optional? It adds pointer semantics to normal objects and allows them to be either set or not, without dynamic allocation.
#include <boost/optional.hpp>
typedef boost::optional<std::vector<DWORD>> vec_opt;
vec_opt get_running_proc_list()
{
DWORD proc_list[1024], size;
if(!EnumProcesses(proc_list, sizeof(proc_list), &size))
{
return 0;
}
vector<DWORD> _procs(proc_list, proc_list + size/sizeof(DWORD));
return _procs;
}
And that's all you need to do, just change the return type. On the calling site:
vec_opt v = get_running_proc_list();
if(v){
// successful and you can now go through the vector, accessing it with *v
vector<DWORD>& the_v = *v;
// use the_v ...
}
You are trying to return two logically distinct bits of information: First, "What are the list of processes?" and second, "Can I compute the list of processes?". I suggest you return those in two distinct variables:
// UNTESTED
bool get_running_proc_list(vector<DWORD>& result)
{
DWORD proc_list[1024], size;
if(!EnumProcesses(proc_list, sizeof(proc_list), &size))
{
return false;
}
result = vector<DWORD>(proc_list, proc_list + size/sizeof(DWORD));
return true;
}
But, I might try to save a couple memcpy's:
// UNTESTED
bool get_running_proc_list(vector<DWORD>& result)
{
result.clear();
result.resize(1024);
DWORD size;
if(!EnumProcesses(&result[0], result.size()*sizeof(DWORD), &size))
{
result.clear();
return false;
}
result.resize(size/sizeof(DWORD));
return true;
}