std::string optimization? [closed] - c++

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
Someone want to explain me which code is faster ? and what is the best way to optimise a string assignment ?
code 1 :
std::string result;
int main()
{
for(int i=0;i<1000;i++)
{
/*some code*/
result = stringVar;
/* some code using result */
}
}
code 2 :
int main()
{
for(int i=0;i<1000;i++)
{
/*some code*/
std::string result = stringVar;
/* some code using result */
}
}
And to assigne value :
std::string var;
var.assign("value");
//or
var="value";
And it's possible to release memory used by the value before to add a new one ?
Thank if you can help me to understand that :)

In the case of:
for (...)
std::string result = blah;
the compiler must construct and destruct result each time through the for loop, probably requiring heap allocation and deallocation calls.
In the case of:
std::string result;
for (...)
result = blah;
the string implementation might be able to optimize some heap allocation and deallocation away by only reallocation when blah is to big to fit in result's current buffer.
var=x and var.assign(x) should result in the same code; I would not expect a substantial difference either way.

The first is probably somewhat faster, because it can re-use the allocated memory from the previous pass; the second one destroys the string at the end of each pass through the loop, so frees the storage for the content of the string. An optimizer that keeps the object around, despite it being defined in the loop body, is violating the language rules.

In Code 1, operator= will be called, this is usually implemented by creating a temp object (using copy constructor) and then swapping the guts of the temp object with the lhs object. So a copy constructor, a swap, and a delete of the temp object (when the method operator=() exits) is done in code 1.
In Code 2, a copy constructor is called, and finally the object will be deleted when the for loop pass ends.
So Code 1 has the extra step of swapping the guts of the string class. Although the implementation of operator= might be not as described above for some string libs and so the best advise is to test it for your environment.

Related

Returning a struct by value vs by reference [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
I want to return multiple values in C++ and I have this snippet of code:
struct returns
{
int row_locs, col_locs;
int row_descriptors, col_descriptors;
double **locs;
double **descriptors;
};
void returns (int &row_locs, int &col_locs, int &row_descriptors, int &col_descriptors, double **locs, double **descriptors)
{
//make some changes in variables
}
The question is "What consumes more time : struct or call by reference?"
The difference is negligible in both cases. You shouldn't worry about these issues until you found them to be really issues. Short answer: do the way you like more and consider different aspects like how you will use the returned values later.
If you pass arguments by reference then they're already allocated on stack or dynamically and their pointed values are filled by the function. Time is spent in copying all the pointers to the stack and in storing at their addresses in called function.
In the second case the whole struct is allocated on stack and filled (probably by a single constructor that is missing in your struct). Time is spent in constructing the object onto the stack and in filling its values.
When function returns something bigger than long (on x86 and other 32 bit processors) or long long (on x86_64 and another 64 bit architectures) it returns pointer to alocated memory and then data is being copied to local structure.
struct example
{
long long a,b,c;
};
example create_new_struct(void)
{
example tmp; //new object is created
tmp.a = 3;
tmp.b = 4;
bmp.c = 5;
return example; //in low-level pointer is returned and all data copied
}
void modify_existing_structure(example & tmp)
{
tmp.a = 3; //setting data directly
tmp.b = 4;
tmp.c = 5;
return;
}
int main(void)
{
example a = create_new_struct(), b; //varaibles are being copied
modify_existing_structure(b); //variables are being set directly
return 0;
}
So you definitly shoud use references. But (as was noticed) your code makes zero sense. You shoud not use anonymous structures and parse all variables separated. In your code you create six pointers instead of one for each function call.
Also, I think you shoud learn more about object-oriented programming.

Keeping track of objects and references [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
If we comment out the emphasized line below we get 777 in the console.
Otherwise we get some garbage like (-534532345).
My environment is Microsoft Visual Studio 2012 Pro.
class C
{
public:
C () { x = 777; }
void ou() {cout << x;}
protected:
int x;
};
class A
{
public:
A(C & rrc) : rc(rrc) {};
void koo () {rc.ou();}
protected:
C & rc;
};
int _tmain(int argc, _TCHAR* argv[])
{
C c;
C * pc = new C;
A a(*pc);
delete pc; // <<<< this line
a.koo();
return 0;
}
Can anyone help me figure out why I am seeing this behavior?
At the point you call a.koo(), you've deleted the underlying object that its rc reference refers to. That's of course UB. What happens next is likely to have consistent behavior on a given platform for a given compilation, and may even output 777 (actually, will likely output 777 since the underlying object was very recently deleted). In your case, it seems that either the memory that had been previously allocated to _tmain()'s pc object has been reallocated to something else that has overwritten it, or else you're using a debug build whose memory allocator explicitly overwrites deleted/freed memory with some fixed value, typically nonzero and not all ones, but something that's otherwise recognizable like 0xAAAAAAAA or 0xDEADDEAD. Since -534532345 is 0xE023AF07 (or 0xFFFFFFFFE023AF07), I'm guessing it's the former (the memory has been allocated to something else which has overwritten it). Since the call to a.koo() in your example immediately follows delete pc, I find it surprising that it's already been overwritten so soon, but technically anything's possible since it's UB.
The delete leaves you with a dangling reference, which you follow, leading to undefined behaviour. It is not a hole in C++ or MS VS. The language allows for many illegal actions to go unchecked, and leave it up to the programmer not to invoke UB.
The code has Undefined Behavior. You are holding the reference of an object which no longer exists. So, rc.ou() behavior is undefined.
If you delete pc, then A::rc will point to garbage location and rc.ou(); will output garbage as well. This is expected behavior and it will do this regardless of the compiler you are using
Btw 99[.99]% of the time you think you've found a bug in a compiler, it really is your bug

Cracker Barrell Puzzle solver in C++ [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
I am implementing a recursive solution to the Cracker Barrel Puzzle.
My recursive function returns a string representation of the state of the solved board and all the steps leading to that state.
At each stage in my recursive function, a valid gameboard is generated and the function is recursively called on the gameboard object.
My problem is: what do I need to return when there are no valid gameboard moves that can be made on the current gameboard object? Currently this scenario is causing the function to crash.
Well you have the problem of determining the base case. For mathematical recursive functions, the base case is trivial, like F(0) for the case of Fibonacci Numbers.
Although, I am not familiar with that game or your exact implementation, if you reach a state when no more recursive call would arise, return a Base value. For numbers, it would be the base value, for strings a zero length string. For the case of Gameboard, use a Default state for every cell to indicate that this is a base case and handle that appropriately on the return.
There are many ways to implement recursive functions. Without any hits as to how you have decided to go (you have hinted that you are returning the game state in a string... std::string?), maybe you simply need an if statement:
std::string recursive_game(std::string &populate)
{
if (...game is finished...) {
...
return populate;
} else {
...
return recursive_game(populate);
}
}
int main()
{
std::string completed_game;
recursive_game(completed_game);
return 0;
}
it seems you have to test your return value and throw an exception in case you can't return a correct value.
you can try adding a sanity check function
void main ()
{
bool validMovesAvailable =true;
string currentMoves;
do
{
currentMoves = doNextMove (currentMoves); //your current function
validMovesAvailable = checkAnyMoreMoves (currentMoves); //sanity check function
}while (validMovesAvailable);
}
You return the number of pegs left on the board. This is the score of the game.

c++ delete pointer issue, can still access data [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
I don't really understand why are those pointer accessible ... any help appreciated
#include <iostream>
class Wicked{
public:
Wicked() {};
virtual ~Wicked() {};
int a;
int b;
};
class Test
{
public:
Test() {};
virtual ~Test() {};
int c;
Wicked * TestFunc()
{
Wicked * z;
c = 9;
z = new Wicked;
z->a = 1;
z->b = 5;
return z;
};
};
int main()
{
Wicked *z;
Test *t = new Test();
z = t->TestFunc();
delete z;
delete t;
// why can I set 'z' when pointer is already destroyed?
z->a = 10;
// why does z->a print 10?
std::cout << z->a << std::endl;
// why does t->c exist and print correct value?
std::cout << t->c << std::endl;
//------------------------------------------------------
int * p = new int;
*p = 4;
// this prints '4' as expected
std::cout << *p << std::endl;
delete p;
// this prints memory address as expected
std::cout << *p << std::endl;
return 0;
}
Deleting a pointer doesn't zero out any memory because to do so would take CPU cycles and that's not what C++ is about. What you have there is a dangling pointer, and potentially a subtle error. Code like this can sometimes work for years only to crash at some point in the future when some minor change is made somewhere else in the program.
This is a good reason why you should NULL out pointers when you've deleted the memory they point to, that way you'll get an immediate error if you try to dereference the pointer. It's also sometimes a good idea to clear the memory pointed to using a function like memset(). This is particularly true if the memory pointed to contains something confidential (e.g. a plaintext password) which you don't want other, possibly user facing, parts of your program from having access to.
That's undefined behaviour. Anything can happen.You were lucky this time. Or perhaps unlucky since it would be preferable to get a runtime error! Next time round maybe you'll get a runtime error.
It's not really very useful to reason about why you see a particular manifestation of undefined behaviour. It's best to stick to the well-defined behaviour about which you can reason.
C++ won't stop you from writing to an arbitrary location in memory. When you allocate memory with new or malloc, C++ finds some unused space in memory, marks it as allocated (so that it doesn't accidentally get handed out again), and gives you its address.
Once you delete that memory however, C++ marks it as free and may hand it out to anyone that asks for it. You can still write to it and read from it, but at this point, someone else might be using it. When you write to that place in memory, you may be overwriting some value you have allocated elsewhere.
Here
// why can I set 'z' when pointer is already destroyed?
z->a = 10;
z still points at a memory location.
But it no longer blongs to you. You have passed it to delete and said take care of this pointer. What it does is no longer your concern. Its like when you sell your car; it still exists but its not yours so opening the door and looking in may be possible, but it may result in the police arresting you.
Same with deleted pointers the memory exists but does not belong to you.
If you look inside it may work, but it may also cause a segmentation fault as the library has flushed the page (you never know).
delete z; just deallocates the memory z was pointing to, it does not destroy the pointer itself.
So z becomes a wild pointer.
Because deleting a block of memory does not zero the value of all pointers that point to it. Deleting memory merely makes a note that the memory is available to be allocated for some other purpose. Until that happens, the memory may appear to be intact -- but you can't count on it, and on some compiler/runtime/architecture combinations, your program will behave differently -- it may even crash.

Beginner's question: Why can't I access an object's members when it is in a vector? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
This is probably a basic question.
I have a vector of a data type 'player' that I have defined myself using a struct:
struct player {
string player_name;
string label;
...
...
}
I then having a function taking a vector of these player data types as a parameter and I want to access the members in the struct i.e.
void foo(vector<player> players) {
cout << players.at(0).player_name;
}
The at(i) works because it is a function of vector. However, I can't access player_name. Why is this and how can I solve it? Apologies if this is basic and boring.
Following code accesses player in vector:
#include <string>
#include <vector>
using namespace std;
struct player {
string player_name;
string label;
};
int main() {
vector <player> p;
p.push_back( player() );
p.at(0).player_name = "fred";
}
Your problem is that foo() returns but you don't see the side-effect of the changed player_name, I guess?
It's because you've passed the vector to foo() by value rather than reference. foo() is operating on a copy of the vector rather than whatever original you passed to it, so the player_name change is lost when the function ends.
Try changing the function signature to void foo(vector<player>& players).
(Note that I've added an ampersand to make the parameter a reference.)
You should not get a compilation error since the code you posted is fine. If you are getting a runtime-error make sure you have inserted at least one object into the vector before you try to access it.
just speculation
if you get a compile error:
probably you declare a class instead of a struct.
if you get a runtime error:
the vector is empty
no error but not result:
you haven't flush the stream. Add std::endl or call std::cout.flush()