The cppreference page says about std::basic_string::swap that it has constant complexity. As I assume that means that copying contents cannot happen, only the swapping of pointers, or similar. I wrote a test code and experienced that it does move contents under VS2010. Test code:
std::string s1("almafa");
std::string s2("kortefa");
std::cout << "s1.c_str(): "<< (void*)s1.c_str() << std::endl;
std::cout << "s2.c_str(): "<< (void*)s2.c_str() << std::endl;
std::cout << "SWAP!" << std::endl;
s1.swap(s2);
std::cout << "s1.c_str(): "<< (void*)s1.c_str() << std::endl;
std::cout << "s2.c_str(): "<< (void*)s2.c_str() << std::endl;
Output on g++ 4.6.3
s1.c_str(): 0x22fe028
s2.c_str(): 0x22fe058
SWAP!
s1.c_str(): 0x22fe058
s2.c_str(): 0x22fe028
Output on VS2010
s1.c_str(): 000000000022E2D0
s2.c_str(): 000000000022E320
SWAP!
s1.c_str(): 000000000022E2D0
s2.c_str(): 000000000022E320
Is it a divergency from the standard or something is happening that I have no knowledge about?
Some implementation of std::string use the short string optimization:
From How is std::string implemented?:
a "short string optimization" (SSO) implementation. In this variant, the object contains the usual pointer to data, length, size of the dynamically allocated buffer, etc. But if the string is short enough, it will use that area to hold the string instead of dynamically allocating a buffer.
So the swap in your case does a copy but of fixed size, so O(1).
Related
I wanted to check that if my string resized, will the address of string change or not. So I wrote the below program whereby initial capacity was 1, and then it changed to 30, I'd assume that on capacity change the string would've moved addresses, but that didnt happen.
Can someone explain why that is?
string s = "1";
string& s1 = s;
cout << &s << " capacity is " << s.capacity() << endl;
cout << &s1 << endl;
s = "sdhflshdgfljasdjflkasdfhalsjdf";
cout << &s << " capacity is " << s.capacity() << endl;
cout << &s1 << endl;
Output is
0x7ffc11fc08d0 capacity is 1
0x7ffc11fc08d0
0x7ffc11fc08d0 capacity is 30
0x7ffc11fc08d0
The string variable will not move, but the buffer it holds a pointer to internally may move to a new address as it allocates more memory. This is not observable by taking the address of the variable though. If you print the pointer returned by the .data() member (by casting it to a void pointer) you may see a change (assuming the new size is enough to trigger reallocation - many strings use a small string optimization with a pre-allocated buffer, so you need to grow beyond that).
I don't know exactly how to define what I am searching, but, here I go:
Since the library libjsoncpp exists and lets us hold a value in an object that is "json based", which means, an integer, an unsigned number, double, string or null... (also arrays and objects that can be seen -or I perceive- as pointer based objects to other objects),
... is there any kind of library in which we could operate with those data, more or less as we do in javascript?
#include "somemagiclib.h"
magicnamespace::jsonlike_o value1=10;
int integervalue=15;
magicnamespace::jsonlike_o value2="hello_world";
std::string anything="anything";
magicnamespace::jsonlike_o value3="10.3";
magicnamespace::jsonlike_b result;
value3=value2+value1;
std::cout << "value3 is: " << value3.asString() << std::endl;
/*value3 is: 21*/
std::cout << (value2+value1).asString() << std::endl;
/*hello_world10*/
std::cout << (value1+value3).asString() << std::endl;
/*20*/
std::cout << (value3+value1).asString() << std::endl;
/*10.310*/
std::cout << (value1<value3).asString() << std::endl;
/*true*/
std::cout << (value1+integervalue).asString() << std::endl;
/*25*/
std::cout << (value1+anything).asString() << std::endl;
/*18*/
std::cout << (value1>=integervalue).asString() << std::endl;
/*false*/
std::cout << (value2+integervalue).asString() << std::endl;
/*hello_world15*/
std::cout << (value2+anything).asString() << std::endl;
/*hello_worldanything*/
We could easily reach to the ask "what for?" (...or even "wtf for?"). In fact, I am working on a project that requires a part of json processing to compare values that are obtained from part based ports transmitting in serial protocols, compared with values that are obtained from json based configured files.
Being able to code or preview the future scenarios is becoming difficult, since we also have to preview incoming values from JsonRPC based objects, so the code may become expensive to generate or to maintain.
Do you know if there's any kind of library that implements this kind of "non-typed" type in C++?
In case of not knowing, do you think that this kind of library deserves the efforts to be created?
Thank you very much for your attention.
Look into crow c++. its not just json stuff, its pretty much flask for c++. might be useful. it's also just a header file, so no installation etc is needed
I'm using memcpy to copy the content of std:vectors<> to primitve Arrays. For datatypes like int, float, double etc. it worked well. As I started to copy a boolvector I encountered a problem namely I got strange values.
First I started to make an test output for a float vector:
std::vector<float> test1 (3,0);
cout << "Sizeof test1[0] : " << sizeof(test1[0]) << endl
<< "Memoryaddress 0: " << &test1[0] << endl
<< "Memoryaddress 1: " << &test1[1] << endl
<< "Memoryaddress 2: " << &test1[2] << endl;
The output is:
Sizeof test1[0]: 4
Memoryaddress 0: 02793820
Memoryaddress 1: 02793824
Memoryaddress 2: 02793828
And this is what I expect. The float size is 4 Byte and the distance to the next float value is 4 Byte. When I do this for bool the output looks like this:
std::vector<bool> test (3,0);
cout << "Sizeof test[0]: " << sizeof(test[0]) << endl
<< "Memoryaddress 0: " << &test[0] << endl
<< "Memoryaddress 1: " << &test[1] << endl
<< "Memoryaddress 2: " << &test[2] << endl;
The output is:
Sizeof test[0]: 16
Memoryaddress 0: 011EF94C
Memoryaddress 1: 011EF93C
Memoryaddress 2: 011EF92C
Why is the size of bool 16 Byte? It seems like a total overkill to me. Are there explanations for this?
Unlike other specialisations of vector, vector<bool> does not manage a dynamic array of bool objects. Instead, it is supposed to pack the boolean values into a single bit each.
Since individual bits are not addressable, test[0] cannot simply be a reference to bool. Instead, it is an class type vector<bool>::reference that can be converted to bool (to get the value), and assigned from bool (to modify the vector element).
This means that vector<bool> doesn't entirely meet the requirements of a standard container, and can't be used if you need references or pointers to its elements. If you do require a "real" container with addressable elements, consider vector<char> or deque<bool> instead.
std::vector<bool> is a specialized version of vector, which is optimizes for space.
The storage is not necessarily an array of bool values, but the library implementation may optimize storage so that each value is stored in a single bit.
Elements are not constructed using the allocator object, but their value is directly set on the proper bit in the internal storage.
More information: http://www.cplusplus.com/reference/vector/vector-bool/
Why after using strdup(value) (int)value returns you different output than before?
How to get the same output?
My short example went bad, please use the long one:
Here the full code for tests:
#include <stdio.h>
#include <iostream>
int main()
{
//The First Part
char *c = "ARD-642564";
char *ca = "ARD-642564";
std::cout << c << std::endl;
std::cout << ca << std::endl;
//c and ca are equal
std::cout << (int)c << std::endl;
std::cout << (int)ca << std::endl;
//The Second Part
c = strdup("ARD-642564");
ca = strdup("ARD-642564");
std::cout << c << std::endl;
std::cout << ca << std::endl;
//c and ca are NOT equal Why?
std::cout << (int)c << std::endl;
std::cout << (int)ca << std::endl;
int x;
std::cin >> x;
}
Because an array decays to a pointer in your case, you are printing a pointer (ie, on non-exotic computers, a memory address). There is no guarantee that a pointer fits in an int.
In the first part of your code, c and ca don't have to be equal. Your compiler performs a sort of memory optimization (see here for a full answer).
In the second part, strdup allocates dynamically a string twice, such that the returned pointers are not equal. The compiler does not optimize these calls because he does not seem to control the definition of strdup.
In both cases, c and ca may not be equal.
"The strdup() function shall return a pointer to a new string, which is a duplicate of the string pointed to by s1." source
So it's quite understandable that the pointers differ.
Well I just noticed that by changing the position -in microsoft visual studio- through "seekp" I implicitelly also change the read-position, when handling files.
I am wondering however if this is "portable" behaviour? Can I expect the position of reading & writing to be always the same? And consequently: will tellp & tellg always return the same value?
For file positions they are the same. In other words there is only one pointer maintained.
From 27.9.1.1p3:
A joint file position is maintained for both the input sequence and
the output sequence.
So, seekg and seekp are interchangeable for file streams. However, this is not true for other types of streams, as they may hold separate pointers for the put and get positions.
Update: So from all the comments and everything, it seems that for fstream, seekp and seekg use the same pointer. But for stringstream and probably other non-file based streams, they are separate.
Original Post:
Doesn't work for me on linux with g++ 4.7.2. They seem to be independent:
#include <sstream>
#include <iostream>
int main(int, char**) {
std::stringstream s("0123456789");
std::cout << "put pointer: " << s.tellp() << std::endl;
std::cout << "get pointer: " << s.tellg() << std::endl;
std::cout << std::endl;
s.seekp(2);
std::cout << "put pointer: " << s.tellp() << std::endl;
std::cout << "get pointer: " << s.tellg() << std::endl;
std::cout << std::endl;
s.seekg(4);
std::cout << "put pointer: " << s.tellp() << std::endl;
std::cout << "get pointer: " << s.tellg() << std::endl;
std::cout << std::endl;
}
Output:
put pointer: 0
get pointer: 0
put pointer: 2
get pointer: 0
put pointer: 2
get pointer: 4
Also the behaviour you describe sounds like it doesn't comply with the quotes here:
Sets the position of the get pointer. The get pointer determines the
next location to be read in the source associated to the stream.
and here:
Sets the position of the put pointer. The put pointer determines the location in the
output sequence where the next output operation is going to take
place.