vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> result;
queue<TreeNode *> que;
if (root != nullptr) {
que.emplace(root);
}
while (!que.empty()) {
vector<int> level;
int size = que.size();
for (int i = 0; i < size; i++) {
auto *front = que.front();
que.pop();
level.emplace_back(front->val);
if (front->left != nullptr) {
que.emplace(front->left);
}
if (front->right != nullptr) {
que.emplace(front->right);
}
}
result.emplace_back(move(level));
}
return result;
}
Problem: https://leetcode.com/problems/binary-tree-level-order-traversal/description/
Above is the function that returns a vector>.
However, since I initialized the vector as a local variable vector<vector<int>> result; does it mean that it is a code smell for me to return it?
Since the vector is a local variable, it is allocated on the stack and the vector will get destroyed when this function call is over.
Should I have done this instead auto results = new vector<vector<int>>
No.
Since the software will not allow me to stop at that, I will elaborate. The "No" applies to the question only. I have not checked the code for errors. So, no, it is not wrong to return the result as written. There is no cost involved. Any modern compiler will use return-value optimization to return the result.
It would be very bad form to use operator new. Doing so would put the burden of deleting the object upon the calling function. Search for "C++ RAII".
Related
I am using VS2017 and do not understand why I am getting compiler "Warning C6001 Using uninitialized memory 'values'", on line if(values!= NULL) in catch block.
#include <windows.h>
typedef enum
{
VALUE_STATE_NOT_AVAILABLE = 1,
VALUE_STATE_ERROR = 2,
VALUE_STATE_VALID = 3,
VALUE_STATE_UNKNOWN = 4
} XyzValueState_t;
class XyzValue
{
private: XyzValueState_t _valueState;
protected: XyzValue( XyzValueState_t valueState ) {
_valueState = valueState;
}
}
typedef XyzValue* xyzValuePtr_t;
main(){
bool flag=true;
xyzValuePtr_t* values = NULL;
unsigned int _argument=2;
if(flag==true) {
values = new PCLValuePtr_t[2]{ NULL,NULL };
try {
values[0] = new PCLUnsignedInteger(_argument);
values[1] = new PCLUnsignedInteger(_argument);
xyz(values); // passing the value to third party function which returns void
}
catch(...) {
if(values!= NULL){
for(int k = 0; k < 1; k++) {
delete values[k];
values[k] = NULL;
}
delete [] values;
values = NULL;
}
}
}
}
Thank you in advance for your help and guidance
not quite sure why your compiler thinks this might be unitialized.
But, in C++, I'd argue that the way you're building your array with new is unnecessarily complicated and error prone. This look like someone from 1993 tried to write C++11. You have initializer lists, but you don't use RAII!
so, do the C++ thing and use C++'s deterministic object lifetime to manage memory. For an array of objects, this is elegantly handled by std::vector:
#include <vector>
class XyzValue;
main(){
bool flag=true;
unsigned int _argument=2;
if(flag==true) {
std::vector<XyzValue> values(2); // default initialization for two XyzValues.
try {
xyz(values.data()); // if you need the raw contiguous memory. **You probably don't.**
}
catch(...) {
// all the manual deletion not necessary anymore, because at end of scope, things are deconstructed automatically, so this catch clause now is empty.
}
}
}
See how this is much shorter, better readable, has the same functionality, but none of the need to manually delete anything? That's why we write C++ instead of C.
I am a beginner at C++ and am have some issues with 2 separate errors. Unable to access memory and stack overflow.
This is my implementation for a Trie Tree, using pointers, of words containing characters a-z. When running tests, I can successfully add several hundred, or even thousands of nodes without issue, until it eventually crashes. Error: Unable to access memory. I more often get this error when I am trying to run a query and use the "isAWord" function. I also get a stack overflow when I try to run the deconstructor. Any help is appreciate, as I've spent 2 days trying to debug with little success.
#include "Trie.h"
#include <iostream>
#include <iterator>
#include <sstream>
using namespace std;
//sets up tree
Trie::Trie()
{
for (int i = 0; i < ALPH; i++)
this->childs[i] = nullptr;
endNode = false;
}
//add 'userInput' string to trie
void Trie::addAWord(std::string userInput)
{
Trie* start = this;
for (int i = 0; i < userInput.length(); i++)
{
int index = userInput[i] - 'a';
if (start->childs[index] == nullptr)
start->childs[index] = new Trie();
start = start->childs[index];
}
start->endNode = true;
}
//returns true if 'wordFind' is in tree
bool Trie::isAWord(std::string wordFind)
{
if (this == nullptr)
return false;
Trie* start = this;
for (int i = 0; i < wordFind.length(); i++)
{
int index = wordFind[i] - 'a';
start = start->childs[index];
if (start == nullptr)
return false;
}
return start->endNode;
}
//returns a vector containing the words in tree with prefix 'prefFind'
vector<std::string> Trie::allWordsStartingWithPrefix(std::string prefFind)
{
string pres = PrefixRec(prefFind,*this);
stringstream preStream(pres);
istream_iterator<std::string> begin(preStream), end;
vector<std::string> stringSet(begin, end);
copy(stringSet.begin(), stringSet.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
return stringSet;
}
//helper method for AllWordsStartingWithPrefix
std::string Trie::PrefixRec(std::string& key, Trie const temp)
{
if (temp.endNode)
return(key + " ");
for (char index = 0; index < ALPH; ++index)
{
index = key[index] - 'a';
Trie const* curChild = temp.childs[index];
if (curChild)
{
key.push_back(index);
PrefixRec(key, *curChild);
key.pop_back();
}
}
}
//copy cons and assignment op
Trie& Trie::operator=(const Trie& other)
{
Trie* newPtr = new Trie(other);
other.~Trie();
return *newPtr;
}
//deconstructor
Trie::~Trie()
{
if (this == nullptr)
return;
for (int i = 0; i < ALPH; i++)
{
if (childs[i] != nullptr)
childs[i]->~Trie();
}
delete this;
return;
}
#include <iostream>
#include <vector>
#include <string>
#define ALPH 26
class Trie
{
public:
bool endNode;
Trie* childs[ALPH];
Trie();
void addAWord(std::string key);
bool isAWord(std::string key);
std::vector<std::string> allWordsStartingWithPrefix(std::string key);
Trie& operator=(const Trie& other);
std::vector<std::string> wordsWithWildcardPrefix(std::string);
std::string PrefixRec(std::string& key, Trie const temp);
~Trie();
};
I also get a stack overflow when I try to run the deconstructor.
This is because of this line:
delete this;
This is what a delete does
The delete expression invokes the destructor (if any) for the object
that's being destroyed,
You can imagine why calling delete from within the destructor would be problematic. (Hint: Infinite recursion)
You don't want any delete this in your code.
Once you get rid of this, there are other issues.(Although you may live just by fixing this). For instance calling the destructor explicitly as you are doing in this line(and several other lines)
other.~Trie();
From iso cpp:
Should I explicitly call a destructor on a local variable?
No!
The destructor will get called again at the close } of the block in which the local was created. This is a guarantee of the language; it happens automagically; there’s no way to stop it from happening. But you can get really bad results from calling a destructor on the same object a second time! Bang! You’re dead!
Replace the explicit destructor calls with delete and let it call the destructor correctly.
I would recommend replace any raw pointers and new and delete with smart pointer. Start with shared_ptr to begin with. (raw_pointers are so 2010 ;))
Footnote: Get rid of these checks. They are non-idiomatic. It's ok and desirable for the caller to burn when calling a member function on a nullptr
if (this == nullptr)
return false;
I am using a vector of vector in my A3 code. I sort the vector of vector's at insertion. I store my keys in the 0th index of each sub vector.
In my size method, I am trying to use the direct call for checking the size. The code below outlines my attempt. However, I get a segmentation fault on execution. Can anyone help me understand the reason for the same?
vector<vector<int>> pairs; //sorted in the insert method
int size(int key) const {
if( pairs[key].size() == 0 ) { return -1; }
else { return pairs[key].size() - 1; }
}
I have implemented the same successfully previously, however, it was a very inefficient solution using linear search. Here is the code for the same:
int size(int key) const
{
for( int i=0; i<pairs.size(); i++)
{
if( pairs[i][0] == key )
{
return pairs[i].size() - 1;
}
}
return -1;
}
This code is not enough to tell you what is happening, we can only make a guess.
I would say that your leak comes from the method data: you create a copy of the data and then return a pointer to this copy. It would be better to return an unique_ptr, so the memory is released automatically.
If you cannot change the definition of the method, then you could change the body of the method by this one:
int length = size(key);
if( length == -1 )
return nullptr;
for( int i=0; i<pairs.size(); i++)
{
if( pairs[i][0] == key )
{
return &pairs[i][1];
}
}
return nullptr;
Bear with me, I'm new to C++. I'm trying to update a value which is stored in a vector, but I'm getting this error:
non-const lvalue reference to type 'Node'
I'm using a simple wrapper around std::vector so I can share methods like contains and others (similar to how the ArrayList is in Java).
#include <vector>
using namespace std;
template <class T> class NewFrames {
public:
// truncated ...
bool contains(T data) {
for(int i = 0; i < this->vec->size(); i++) {
if(this->vec->at(i) == data) {
return true;
}
}
return false;
}
int indexOf(T data) {
for(int i = 0; i < this->vec->size(); i++) {
if(this->vec->at(i) == data) {
return i;
}
}
return -1;
}
T get(int index) {
if(index > this->vec->size()) {
throw std::out_of_range("Cannot get index that exceeds the capacity");
}
return this->vec->at(index);
}
private:
vector<T> *vec;
};
#endif // A2_NEWFRAMES_H
The class which utilizes this wrapper is defined as follows:
#include "Page.h"
#include "NewFrames.h"
class Algo {
private:
typedef struct Node {
unsigned reference:1;
int data;
unsigned long _time;
Node() { }
Node(int data) {
this->data = data;
this->reference = 0;
this->_time = (unsigned long) time(NULL);
}
} Node;
unsigned _faults;
Page page;
NewFrames<Node> *frames;
};
I'm at a point where I need to reference one of the Node objects inside of the vector, but I need to be able to change reference to a different value. From what I've found on SO, I need to do this:
const Node &n = this->frames->get(this->frames->indexOf(data));
I've tried just using:
Node n = this->frames->get(this->frames->indexOf(data));
n.reference = 1;
and then viewing the data in the debugger, but the value is not updated when I check later on. Consider this:
const int data = this->page.pages[i];
const bool contains = this->frames->contains(Node(data));
Node node = this->frames->get(index);
for(unsigned i = 0; i < this->page.pages.size(); i++) {
if(node == NULL && !contains) {
// add node
} else if(contains) {
Node n = this->frames->get(this->frames->indexOf(data));
if(n.reference == 0) {
n.reference = 1;
} else {
n.reference = 0;
}
} else {
// do other stuff
}
}
With subsequent passes of the loop, the node with that particular data value is somehow different.
But if I attempt to change n.reference, I'll get an error because const is preventing the object from changing. Is there a way I can get this node so I can change it? I'm coming from the friendly Java world where something like this would work, but I want to know/understand why this doesn't work in C++.
Node n = this->frames->get(this->frames->indexOf(data));
n.reference = 1;
This copies the Node from frames and stores the copy as the object n. Modifying the copy does not change the original node.
The simplest "fix" is to use a reference. That means changing the return type of get from T to T&, and changing the previous two lines to
Node& n = this->frames->get(this->frames->indexOf(data));
n.reference = 1;
That should get the code to work. But there is so much indirection in the code that there are likely to be other problems that haven't shown up yet. As #nwp said in a comment, using vector<T> instead of vector<T>* will save you many headaches.
And while I'm giving style advice, get rid of those this->s; they're just noise. And simplify the belt-and-suspenders validity checks: when you loop from 0 to vec.size() you don't need to check that the index is okay when you access the element; change vec.at(i) to vec[i]. And in get, note that vec.at(index) will throw an exception if index is out of bounds, so you can either skip the initial range check or keep the check (after fixing it so that it checks the actual range) and, again, use vec[index] instead of vec.at(index).
I would like to set pointers to some elements in my vector array to NULL (based on a criteria), and then check whether an element pointer is NULL. If the pointer pointing that element is NULL, I remove the element from my vector array.
My compiler is giving me an error, saying that the address expression must be an lvalue or function designator and I do not understand why (line location commented in code). Since I am taking the address of the value using &, am I not seeing if the pointer pointing to that element is NULL?
I included the preceding code as the error may lie there,
Relevant code:
vector<particle> pl = c.particlelist;
vector<particle> noncollision = c.particlelist;
vector<vector<particle>> collisionlist = new vector<vector<particle>>();
for (int i = 0; i < c.numparticles-1; i++){
particle first = pl[i];
for (int j = i+1; j < c.numparticles; j++)
{
particle second = pl[j];
double d = distance(first, second);
if (d==0)
{
vector<particle> temp = {pl[i], pl[j]};
collisionlist.push_back(temp);
noncollision[i].setxposint(NULL);
noncollision[j].setxposint(NULL);
}
else
{
}
}
}
int j = 0;
for (int i = 0; i < noncollision.size(); i++)
{
if (&(noncollision[i].getxpos()) == NULL) ////// ERROR HERE
{
noncollision.erase(noncollision.begin()+i);
}
else
{
j++;
}
}
I am new to C++, and if you could suggest a more elegant way to do this, or a fix, it would be much appreciated. I also assume that my method of setting the pointer to an element, noncollision[i].setxposint(NULL); is correct? Can I return an integer using a function, and take the address?
Functions for getxpos and setxposint:
int particle::getxpos(){
return xpos;
}
void particle::setxposint(int b){
xpos = b;
}
You're using & to take a pointer to a temporary vale (the return from getxpos) which isn't allowed; since a temporary will be going away, the address won't be useful in any way so the language doesn't allow it. It certainly wouldn't ever be NULL even if you could get its address.
noncollision[i].setxposint(NULL);
All that line is doing is setting xpos to zero. Generally the term NULL is used with pointers, and 0 is used with things like integers. NULL is usually a macro for 0L anyway.
&(noncollision[i].getxpos()) == NULL
What this is doing, which is incorrect, is attempting to take the address of the return value from the member method getxpos() and compare it to NULL. Whereas what you really want to do is simply see if the function returns zero. So simply change this line to:
noncollision[i].getxpos() == 0
I'll explain why the compiler doesn't understand what you mean.
When you write
&(someFunction())
you are asking for the address of the thing that the function returns. But functions return values. A value doesn't have an address. Variables have addresses.
When something is a word of memory (which will contain a value), it can be used as an lvalue (left-value), because you can put things into that word of memory:
int b = 1; //make room for an `int` on the stack, then put a `1` there.
When something is just a value, it can only ever be used as an rvalue. The following would not compile, for the same reason that your code would not:
int b; //make room for an `int` on the stack.
42 = b; //ERROR, this makes no sense.
if (42 == NULL) { std::cout << "this is never true" << std::endl; }
&42; //ERROR, 42 isn't a piece of memory, it's a value.
(Caveat: you can use values to refer to words in memory: this usage is called a pointer, e.g.
int b = 1;
*((int *)(42)) = b;
meaning "put the value of b into the memory which has the address 42. This compiles fine (but crashes if you're not allowed to write to the memory at 42.)
It looks to me you're trying to keep track of 'visited' items, not sure exactly in which way.
Instead of "modifying" the items, you could use an "external" mark. A set looks to be fine here. You could use a set of iterators into the particle list, or in this case a set of indices (i,j) which will likely be more stable.
Here's a start:
#include <vector>
#include <set>
struct particle { };
double distance(particle const&, particle const&) { return 1.0; }
struct context
{
std::size_t numparticles;
std::vector<particle> particlelist;
context() : numparticles(100), particlelist(numparticles) {}
};
static context c;
int main()
{
using std::vector;
using std::size_t;
vector<particle> pl = c.particlelist;
vector<vector<particle>> collisionlist;
std::set<size_t> collision;
for(size_t i = 0; i < c.numparticles-1; i++)
{
particle first = pl[i];
for(size_t j = i+1; j < c.numparticles; j++)
{
particle second = pl[j];
double d = distance(first, second);
if(d < 0.0001)
{
collisionlist.push_back({pl[i], pl[j]});
collision.insert(i);
collision.insert(j);
}
else
{
}
}
}
for(size_t i = 0; i < pl.size(); i++)
{
if(collision.end() != collision.find(i))
{
// do something
}
}
// alternatively
for (int index : collision)
{
particle& p = pl[index];
// do something
}
}
NOTE Be very very wary of floating point comparison like
if (d==0.0) // uhoh
because it will likely not do what you expect
How dangerous is it to compare floating point values?
What is the most effective way for float and double comparison?
Is floating-point == ever OK?
It seems that you are trying to check pairs of points for collisions. You then record for each point whether it has any collision. This is best handled by a simple list of flags:
std::vector<bool> has_collision(c.numparticles, false); // init: no collisions found
Afterwards:
if (d==0)
{
has_collision[i] = true;
has_collision[j] = true;
}
At the end, iterate over the list of flags and get the points that have no collisions:
for (size_t i = 0; i < c.numparticles; ++i)
{
if (!has_collision[i])
{
// whatever
// possibly push_back pl[i] into some list
}
}
In addition: using a vector to hold a pair (i,j) of points is confusing. Standard library has the std::pair type for purposes such as this.
Also: you don't need explicit dynamic allocation (new); let Standard Library manage memory for you in a safe, non-confusing way. Instead of
vector<vector<particle>> collisionlist = *new vector<vector<particle>>();
Use
vector<vector<particle>> collisionlist;
(or vector<pair<particle, particle>>, as described above).