Is it a bad idea to use pointers as loop incrementers instead of the usual "int i"? - c++

An example of this would be:
char str[] = "Hello";
int strLength = strlen(str);
for ( char * pc = str;
pc < str + strLength;
pc++)
{
*pc += 2;
}
Edit: Accounted for write-protected memory issue.

My one issue is that you'd have a lot of fun if you leave out the * in *pc in the for loop. Whoops? More generally, it is slightly harder to tell the difference between reassigning the pointer and modifying the value.
However, (though I don't have it handy), Stroustroup himself endorses(see edit) pointer iteration in the C++ Programming Language book. Basically, you can have a pretty terse implementation of string comparison between two char arrays using pointer arithmetic.
In short, I would recommend using such pointers in a "read only" fashion. If you need to write to the array, I would use the more traditional i.
This is, of course, all my personal preference.
Edit: Stroustroup doesn't endorse pointer iteration OVER integer -- he simply uses it at one point in the book, so my reasoning is that he doesn't think its anethema to good practice.

It's ALWAYS a bad idea to use a construct that you don't fully understand. This extends to the people who will have to read your code after you... (I think this is a corollary to the "Don't be a clever programmer" rule)
In this case, if you DO understand, and are fully comfortable with the construct, then there's nothing inherently wrong with it... But usually, if you have to ask if it's a bad idea, then you're not fully comfortable with it...

No, it's not a bad idea, except that you messed it up.
For one, you're writing into a string literal. That's undefined behavior. (It crashes on Windows.) Had you written const char* str = "Hello!" the compiler would have barked at you. Unfortunately there's a (in C++ deprecated, but still allowed) conversion from a string literal to a non-const char* which allows your code to compile. However, what you want is an array which you can write into (and which is pre-initialized). For that use char str[] = "Hello!".
The other, minor, mistake is, that you loop through the string twice: strlen runs along the characters until it finds a '\0', and then you do the same again. It would be better if you checked for that '\0' yourself and avoid the call to strlen altogether.
Here's a fixed version of your loop:
char str[] = "Hello!";
for (char * pc = str; *pc != '\0'; pc++)
{
*pc += 2;
}

It is pretty much the idea behind STL iterators, so no, it's not a bad idea.
A canonical loop working on iterators looks something like this:
for (iter cur = begin(); cur != end(); ++cur)
where iter might be a pointer type, or might be some other iterator. It is basically how all the standard library algorithms are implemented.
However, a better question might be what you're trying to achieve with it. The C++ standard library does it because it enables a similar syntax for iterating over any kind of sequence, not just arrays or other containers which define operator[].
It better expresses your intent, in some cases. Sometimes, you don't care about the loop counter i, so why should it be there?
But in other cases, a plain old for loop, where you have access to the counter variable, makes more sense. Do what best expresses your intent.

It can be confusing to people not used to working with pointers. But there is simply no point in writing
for (int i=0; a[i]!=NULL; ++i){
a[i] = ...;
}
instead of
for (aptr p=a; p!=NULL; ++i){
*p = ...;
}
Use the counter when they are equivalent and a pointer when it makes sense.

It's not always a bad idea, but you need to be careful. Take a look at this article.
https://www.securecoding.cert.org/confluence/display/seccode/ARR38-C.+Do+not+add+or+subtract+an+integer+to+a+pointer+if+the+resulting+value+does+not+refer+to+a+valid+array+element

For C++:
It's not a bad idea at all. In C++ you can use pointers similar to the iterators of the standard library. You can even use the standard library algorithms, such as std::copy, with pointers. It's also feasible to implement std::vector using pointers as iterators. Therefore I prefer iterating using pointers instead of indexes.

I agree with ralu (and Milewski). Many years ago compilers were dumb and would literal-mindedly recalculate the array offset each time (I'm told), so that it was more efficient to use and bump a ptr, yourself. However, they got smarter a few years later (as Milewski says) and could convert the [i] pattern to ptr bumping themselves. In addition, they could use the [i] pattern to unroll the loop a bit, but at that time were not smart enough to see through a programmer's bump-your-own-ptr trick. Now I don't know whether compilers are smart enough nowadays to unroll a loop with hand-rolled simple pointer bumping, possibly so; but I took from that example that the compiler could do cleverer things than had occurred to me, and that the best I could do was make my intent clear and get out of its way. Plus, I think it's easier for another programmer to understand indexes, and that trumps a lot things.

Its not a bad idea in and of itself, but it is unusual. If you expect other people to be working on your code, I'd use the int i version just to reduce confusion.
Either way you've got to worry about the same problems.

It is faster than using higher level objects but as others warn be careful with it. You might have to do it due to the constraints that you are programming to but it is unconventional.
The scope of the variable being in the loop may not be portable as well.

Have a look at the C bible, a.k.a. K&R C (sanitised Amazon link) as they have a discussion about the advantages of both techniques.
Either way, "there be dragons ahead, arr!" so tread very carefully as the road of good pointer arithmetic intentions is paved with the abundant corpses of buffer overflow exploit victims! (-:
In fact, for an excellent discussion and a "wander out on to the thin ice of advanced pointer manipulation" (his term), have a look at Andy Koenig's excellent book "C Traps and Pitfalls" (sanitised Amazon link)
Edit: One thing I forgot to mention, is that I tend to prefer the usual "for (int i = 0; ..) style purely because it is such an ingrained idiom that anyone can see what you're doing with a quick glance. Using pointer arithmetic requires a bit more of a deeper look.
HTH

Sometimes incrementing pointer in a loop looks pretty natural. Take a look at the following code that initialize DirectX texture from GDI+ bitmap:
boost::uint8_t* pDest = static_cast<boost::uint8_t*>(d3dlr.pBits);
const boost::uint8_t* pSrc = static_cast<const boost::uint8_t*>(bitmap_data.Scan0);
for ( UINT i = 0; i < bmp_height; ++i, pSrc += bitmap_data.Stride, pDest += d3dlr.Pitch )
memcpy(pDest, pSrc, bmp_width * BPP);
Here were used two pointers. Each pointer has its own incrementation. I believe that using additional int in this loop will result in deterioration of code readability.

Generaly I stick to this claim by Bartosz Milewski in his great freely avaliable C++ book C++ In Action.
Don’t use pointers unless there is no other way. I leave this kind of optimisations to compilers. It is so simple and common usage that is verry unlikely that compilers can not figure out how to optimise this kind of code.
One last thing from his book:
If your compiler is unable to optimize the human readable, maintainable version of the algorithm, and you have to double as a human compiler-- buy a new compiler! Nobody can afford human compilers any more. So, have mercy on yourself and your fellow programmers who will have to look at your code.

I do not find it problematic to use a pointer as the loop variable. However, I have a few problems with your example:
char str[] = "Hello";
int strLength = strlen(str);
for ( char * pc = str;
pc < str + strLength;
pc++)
{
*pc += 2;
}
strlen iterates over the whole string to figure out the length of the string. Even for a simple example such as this, there is no need for that kind of waste.
This example can be more clearly and succinctly written as:
char str[] = "Hello";
for (char *pc = str; *pc; ++pc) {
*pc += 2;
}
This version is more efficient and easier to understand. It also illustrates there is nothing wrong in principle with using a pointer as the loop variable.

Related

Safe Use of strcpy

Plain old strcpy is prohibited in its use in our company's coding standard because of its potential for buffer overflows. I was looking the source for some 3rd Party Library that we link against in our code. The library source code has a use of strcpy like this:
for (int i = 0; i < newArgc; i++)
{
newArgv[i] = new char[strlen(argv[i]) + 1];
strcpy(newArgv[i], argv[i]);
}
Since strlen is used while allocating memory for the buffer to be copied to, this looks fine. Is there any possible way someone could exploit this normal strcpy, or is this safe as I think it looks to be?
I have seen naïve uses of strcpy that lead to buffer overflow situations, but this does not seem to have that since it is always allocating the right amount of space for the buffer using strlen and then copying to that buffer using the argv[] as the source which should always be null terminated.
I am honestly curious if someone running this code with a debugger could exploit this or if there are any other tactics someone that was trying to hack our binary (with this library source that we link against in its compiled version) could use to exploit this use of strcpy. Thank you for your input and expertise.
It is possible to use strcpy safely - it's just quite hard work (which is why your coding standards forbid it).
However, the code you have posted is not a vulnerability. There is no way to overwrite bits of memory with it; I would not bother rewriting it. (If you do decide to rewrite it, use std::string instead.
Well, there are multiple problems with that code:
If an allocation throws, you get a memory-leak.
Using strcpy() instead of reusing the length is sub-optimal. Use std::copy_n() or memcpy() instead.
Presumably, there are no data-races, not that we can tell.
Anyway, that slight drop in performance is the only thing "wrong" with using strcpy() there. At least if you insist on manually managing your strings yourself.
Deviating from a coding standard should always be possible, but then document well why you decided to do so.
The main problem with strcpy is that it has no length limitation. When taking care this is no problem, but it means that strcpy always is to be accompanied with some safeguarding code. Many less experienced coders have fallen into this pitfall, hence the coding guideline came into practice.
Possible ways to handle string copy safely are:
Check the string length
Use a safe variant like strlcpy, or on older Microsoft compilers, strncpy_s.
As a general strcpy replacement idiom, assuming you're okay with the slight overhead of the print formatting functions, use snprintf:
snprintf(dest, dest_total_buffer_length, "%s", source);
e.g.
snprintf(newArgv[i], strlen(argv[i]) + 1, "%s", argv[i]);
It's safe, simple, and you don't need to think about the +1/-1 size adjustment.

Pointer arithmetic disguised &(array[0])

Today I browsed some source code (it was an example file explaining the use of a software framework) and discovered a lot of code like this:
int* array = new int[10]; // or malloc, who cares. Please, no language wars. This is applicable to both languages
for ( int* ptr = &(array[0]); ptr <= &(array[9]); ptr++ )
{
...
}
So basically, they've done "take the address of the object that lies at address array + x".
Normally I would say, that this is plain stupidity, as writing array + 0or array + 9 directly does the same. I even would always rewrite such code to a size_t for loop, but that's a matter of style.
But the overuse of this got me thinking: Am I missing something blatantly obvious or something subtely hidden in the dark corners of the language?
For anyone wanting to take a look at the original source code, with all it's nasty gotos , mallocs and of course this pointer thing, feel free to look at it online.
Yeah, there's no good reason for the first one. This is exactly the same thing:
int *ptr = array;
I agree on the second also, may as well just write:
ptr < (array + 10)
Of course you could also just make it a for loop from 0-9 and set the temp pointer to point to the beginning of the array.
for(int i = 0, *ptr = array; i < 10; ++i, ++ptr)
/* ... */
That of course assumes that ptr is not being modified within the body of the loop.
You're not missing anything, they do mean the same thing.
However, to try to shed some more light on this, I should say that I also write expressions like that from time to time, for added clarity.
I personally tend to think in terms of object-oriented programming, meaning that I prefer to refer to "the address of the nth element of the array", rather than "the nth offset from the beginning address of the array". Even though those two things are equivalent in C, when I'm writing the code, I have the former in mind - so I express that.
Perhaps that's the reasoning of the person who wrote this as well.
Edit: this is partially incorrect. Read the comments.
The problem with &(array[0]) is that it expands to &(*(array + 0)) which involves an dereference. Now, every compiler will obviously optimize this into the same thing as array + 0, but as far as the language is concerned the dereference can cause UB in places where array + 0 would not.
I think the reason why they wrote it this way was that
&(array[0])
and
&(array[9])
just look similar. Another way would be to write it
array + 0
and
array + 9
respectively. As you already mentioned, they essentially do the same (at least most compilers treat it as the same, I hope).
You could interpret the two different type of expressions differently: The first one can be read as "the address of element 0 / 9". The second one can be read as "array pointer with an element offset of 0 / 9". The first one sounds more high-level, the second more low-level. However, most people tend to use the second form, though.
Now since array + 0 of course is the same as array, you could just write array. I think the point here is that the begin and end of the loop look "analogous" to each other. A question of personal taste.
According to classical mathematics:
Array[n]
refers to the nth element in the array.
To "take the address of" the nth element, the & or address of operator is applied:
&Array[n]
To clear out any assumed ambiguities, parenthesis are added:
&(Array[n])
To a reader, reading from left to right, this expression has the meaning:
Return the address of the element at position 'n'
The insurance may have developed as a protection against old faulty compilers.
Some people consider it more readable than:
Array + n
Sorry, but I am old school and prefer using the '&' version, paren or without. I'll waste my time making code easier to read than worrying about which version takes longer to compile or which version is more efficient.
A clear commented section of code has a higher Return On Investment than a section of code that is micro-optimized for efficiency or uses sections of the language that are unfamilar to non language lawyers.

Difference between std::vector::back and vector::operator[ vector::size() - 1]

is there a difference between:
mvt_act_idx = openCloseList.size()-1;
openCloseList[mvt_act_idx].A += a;
and
openCloseList.back().A += a;
Besides readability?
mvt_act_idx = openCloseList.size()-1;
openCloseList[mvt_act_idx].A += a;
If openCloseList is empty the unsigned subtraction will produce a huge value, which then is used to index the vector. The indexing operator may assert, or not.
openCloseList.back().A += a;
If openCloseList is empty the back operation may assert, or not.
In the case of such error, a fault in back is probably easier to understand.
And anyway, the first code snippet can be in conflict with some guideline to not use unsigned integers as numbers (except where the modulo behavior simplifies and clarifies the code), while the call to back can not be in conflict with any such guideline.
No useful difference.
Using back() directly might be fractionally more efficient, but I doubt it. You could have a look at the generated assembler if you felt really keen. Might make the difference of an instruction or two, depending on how clever your compiler is.
I do note that the former way which uses only size() and [] would be a lot more familiar to people who understand arrays or use similar contructs in any other language; back() is a bit more C++ specific (though it is hardly a cryptic idiom).

C++ valarray vs. vector

I like vectors a lot. They're nifty and fast. But I know this thing called a valarray exists. Why would I use a valarray instead of a vector? I know valarrays have some syntactic sugar, but other than that, when are they useful?
valarray is kind of an orphan that was born in the wrong place at the wrong time. It's an attempt at optimization, fairly specifically for the machines that were used for heavy-duty math when it was written -- specifically, vector processors like the Crays.
For a vector processor, what you generally wanted to do was apply a single operation to an entire array, then apply the next operation to the entire array, and so on until you'd done everything you needed to do.
Unless you're dealing with fairly small arrays, however, that tends to work poorly with caching. On most modern machines, what you'd generally prefer (to the extent possible) would be to load part of the array, do all the operations on it you're going to, then move on to the next part of the array.
valarray is also supposed to eliminate any possibility of aliasing, which (at least theoretically) lets the compiler improve speed because it's more free to store values in registers. In reality, however, I'm not at all sure that any real implementation takes advantage of this to any significant degree. I suspect it's rather a chicken-and-egg sort of problem -- without compiler support it didn't become popular, and as long as it's not popular, nobody's going to go to the trouble of working on their compiler to support it.
There's also a bewildering (literally) array of ancillary classes to use with valarray. You get slice, slice_array, gslice and gslice_array to play with pieces of a valarray, and make it act like a multi-dimensional array. You also get mask_array to "mask" an operation (e.g. add items in x to y, but only at the positions where z is non-zero). To make more than trivial use of valarray, you have to learn a lot about these ancillary classes, some of which are pretty complex and none of which seems (at least to me) very well documented.
Bottom line: while it has moments of brilliance, and can do some things pretty neatly, there are also some very good reasons that it is (and will almost certainly remain) obscure.
Edit (eight years later, in 2017): Some of the preceding has become obsolete to at least some degree. For one example, Intel has implemented an optimized version of valarray for their compiler. It uses the Intel Integrated Performance Primitives (Intel IPP) to improve performance. Although the exact performance improvement undoubtedly varies, a quick test with simple code shows around a 2:1 improvement in speed, compared to identical code compiled with the "standard" implementation of valarray.
So, while I'm not entirely convinced that C++ programmers will be starting to use valarray in huge numbers, there are least some circumstances in which it can provide a speed improvement.
Valarrays (value arrays) are intended to bring some of the speed of Fortran to C++. You wouldn't make a valarray of pointers so the compiler can make assumptions about the code and optimise it better. (The main reason that Fortran is so fast is that there is no pointer type so there can be no pointer aliasing.)
Valarrays also have classes which allow you to slice them up in a reasonably easy way although that part of the standard could use a bit more work. Resizing them is destructive and they lack iterators they have iterators since C++11.
So, if it's numbers you are working with and convenience isn't all that important use valarrays. Otherwise, vectors are just a lot more convenient.
During the standardization of C++98, valarray was designed to allow some sort of fast mathematical computations. However, around that time Todd Veldhuizen invented expression templates and created blitz++, and similar template-meta techniques were invented, which made valarrays pretty much obsolete before the standard was even released. IIRC, the original proposer(s) of valarray abandoned it halfway into the standardization, which (if true) didn't help it either.
ISTR that the main reason it wasn't removed from the standard is that nobody took the time to evaluate the issue thoroughly and write a proposal to remove it.
Please keep in mind, however, that all this is vaguely remembered hearsay. Take this with a grain of salt and hope someone corrects or confirms this.
I know valarrays have some syntactic sugar
I have to say that I don't think std::valarrays have much in way of syntactic sugar. The syntax is different, but I wouldn't call the difference "sugar." The API is weird. The section on std::valarrays in The C++ Programming Language mentions this unusual API and the fact that, since std::valarrays are expected to be highly optimized, any error messages you get while using them will probably be non-intuitive.
Out of curiosity, about a year ago I pitted std::valarray against std::vector. I no longer have the code or the precise results (although it shouldn't be hard to write your own). Using GCC I did get a little performance benefit when using std::valarray for simple math, but not for my implementations to calculate standard deviation (and, of course, standard deviation isn't that complex, as far as math goes). I suspect that operations on each item in a large std::vector play better with caches than operations on std::valarrays. (NOTE, following advice from musiphil, I've managed to get almost identical performance from vector and valarray).
In the end, I decided to use std::vector while paying close attention to things like memory allocation and temporary object creation.
Both std::vector and std::valarray store the data in a contiguous block. However, they access that data using different patterns, and more importantly, the API for std::valarray encourages different access patterns than the API for std::vector.
For the standard deviation example, at a particular step I needed to find the collection's mean and the difference between each element's value and the mean.
For the std::valarray, I did something like:
std::valarray<double> original_values = ... // obviously I put something here
double mean = original_values.sum() / original_values.size();
std::valarray<double> temp(mean, original_values.size());
std::valarray<double> differences_from_mean = original_values - temp;
I may have been more clever with std::slice or std::gslice. It's been over five years now.
For std::vector, I did something along the lines of:
std::vector<double> original_values = ... // obviously, I put something here
double mean = std::accumulate(original_values.begin(), original_values.end(), 0.0) / original_values.size();
std::vector<double> differences_from_mean;
differences_from_mean.reserve(original_values.size());
std::transform(original_values.begin(), original_values.end(), std::back_inserter(differences_from_mean), std::bind1st(std::minus<double>(), mean));
Today I would certainly write that differently. If nothing else, I would take advantage of C++11 lambdas.
It's obvious that these two snippets of code do different things. For one, the std::vector example doesn't make an intermediate collection like the std::valarray example does. However, I think it's fair to compare them because the differences are tied to the differences between std::vector and std::valarray.
When I wrote this answer, I suspected that subtracting the value of elements from two std::valarrays (last line in the std::valarray example) would be less cache-friendly than the corresponding line in the std::vector example (which happens to also be the last line).
It turns out, however, that
std::valarray<double> original_values = ... // obviously I put something here
double mean = original_values.sum() / original_values.size();
std::valarray<double> differences_from_mean = original_values - mean;
Does the same thing as the std::vector example, and has almost identical performance. In the end, the question is which API you prefer.
valarray was supposed to let some FORTRAN vector-processing goodness rub off on C++. Somehow the necessary compiler support never really happened.
The Josuttis books contains some interesting (somewhat disparaging) commentary on valarray (here and here).
However, Intel now seem to be revisiting valarray in their recent compiler releases (e.g see slide 9); this is an interesting development given that their 4-way SIMD SSE instruction set is about to be joined by 8-way AVX and 16-way Larrabee instructions and in the interests of portability it'll likely be much better to code with an abstraction like valarray than (say) intrinsics.
I found one good usage for valarray.
It's to use valarray just like numpy arrays.
auto x = linspace(0, 2 * 3.14, 100);
plot(x, sin(x) + sin(3.f * x) / 3.f + sin(5.f * x) / 5.f);
We can implement above with valarray.
valarray<float> linspace(float start, float stop, int size)
{
valarray<float> v(size);
for(int i=0; i<size; i++) v[i] = start + i * (stop-start)/size;
return v;
}
std::valarray<float> arange(float start, float step, float stop)
{
int size = (stop - start) / step;
valarray<float> v(size);
for(int i=0; i<size; i++) v[i] = start + step * i;
return v;
}
string psstm(string command)
{//return system call output as string
string s;
char tmp[1000];
FILE* f = popen(command.c_str(), "r");
while(fgets(tmp, sizeof(tmp), f)) s += tmp;
pclose(f);
return s;
}
string plot(const valarray<float>& x, const valarray<float>& y)
{
int sz = x.size();
assert(sz == y.size());
int bytes = sz * sizeof(float) * 2;
const char* name = "plot1";
int shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
ftruncate(shm_fd, bytes);
float* ptr = (float*)mmap(0, bytes, PROT_WRITE, MAP_SHARED, shm_fd, 0);
for(int i=0; i<sz; i++) {
*ptr++ = x[i];
*ptr++ = y[i];
}
string command = "python plot.py ";
string s = psstm(command + to_string(sz));
shm_unlink(name);
return s;
}
Also, we need python script.
import sys, posix_ipc, os, struct
import matplotlib.pyplot as plt
sz = int(sys.argv[1])
f = posix_ipc.SharedMemory("plot1")
x = [0] * sz
y = [0] * sz
for i in range(sz):
x[i], y[i] = struct.unpack('ff', os.read(f.fd, 8))
os.close(f.fd)
plt.plot(x, y)
plt.show()
The C++11 standard says:
The valarray array classes are defined to be free of certain forms of
aliasing, thus allowing operations on these classes to be optimized.
See C++11 26.6.1-2.
With std::valarray you can use the standard mathematical notation like v1 = a*v2 + v3 out of the box. This is not possible with vectors unless you define your own operators.
std::valarray is intended for heavy numeric tasks, such as Computational Fluid Dynamics or Computational Structure Dynamics, in which you have arrays with millions, sometimes tens of millions of items, and you iterate over them in a loop with also millions of timesteps. Maybe today std::vector has a comparable performance but, some 15 years ago, valarray was almost mandatory if you wanted to write an efficient numeric solver.

Why is snprintf faster than ostringstream or is it?

I read somewhere that snprintf is faster than ostringstream. Has anyone has any experiences with it? If yes why is it faster.
std::ostringstream is not required to be slower, but it is generally slower when implemented. FastFormat's website has some benchmarks.
The Standard library design for streams supports much more than snprintf does. The design is meant to be extensible, and includes protected virtual methods that are called by the publicly exposed methods. This allows you to derive from one of the stream classes, with the assurance that if you overload the protected method you will get the behavior you want. I believe that a compiler could avoid the overhead of the virtual function call, but I'm not aware of any compilers that do.
Additionally, stream operations often use growable buffers internally; which implies relatively slow memory allocations.
We replaced some stringstreams in inner loops with sprintf (using statically allocated buffers), and this made a big difference, both in msvc and gcc. I imagine that the dynamic memory management of this code:
{
char buf[100];
int i = 100;
sprintf(buf, "%d", i);
// do something with buf
}
is much simpler than
{
std::stringstream ss;
int i = 100;
ss << i;
std::string s = ss.str();
// do something with s
}
but i am very happy with the overall performance of stringstreams.
Some guys would possibly tell you about that the functions can't be faster than each other, but their implementation can. That's right i think i would agree.
You are unlikely to ever notice a difference in other than benchmarks. The reason that c++ streams generally tend to be slower is that they are much more flexible. Flexibility most often comes at the cost of either time or code growth.
In this case, C++ streams are based on stream-buffers. In itself, streams are just the hull that keep formatting and error flags in place, and call the right i/o facets of the c++ standard library (for example, num_put to print numbers), that print the values, well formatted, into the underlying stream-buffer connected to the c++ stream.
All this mechanisms - the facets, and the buffers, are implemented by virtual functions. While there is indeed no mark note, those functions must be implemented to be slower than c stdio pendants that fact will make them somewhat slower than using c stdio functions normally (i benchmark'ed that some time ago with gcc/libstdc++ and in fact noticed a slowdown - but which you hardly notice in day-by-day usage).
Absolutely this is implementation-specific.
But if you really want to know, write two small programs, and compare them. You would need to include typical usage for what you have in mind, the two programs would need to generate the same string, and you would use a profiler to look at the timing information.
Then you would know.
One issue would probably be that the type safety added by ostringstream carries extra overhead. I've not done any measurements, though.
As litb said, standard streams support many things we don't always need.
Some streams implementation get rid of this never used flexibility, see FAStream for instance.
It's quite possible that because sprintf is part of the CRT that is written in assembly. The ostringstream is part of the STL, and probably a little more generically written, and has OOP code/overhead to deal with.
Yes, if you run the function below on a few million numbers with Visual C++ 5.0, the first version takes about twice as long as the second and produces the same output.
Compiling tight loops into a .exe and running the Windows timethis something.exe' or the Linuxtime something' is how I investigate most of my performance curiosities. (`timethis' is available on the web somewhere)
void Hex32Bit(unsigned int n, string &result)
{
#if 0
stringstream ss;
ss
<< hex
<< setfill('0')
<< "0x" << setw(8) << n
;
result = ss.str();
#else
const size_t len = 11;
char temp[len];
_snprintf(temp, len, "0x%08x", n);
temp[len - 1] = '\0';
result = temp;
#endif
}
One reason I know that the printf family of functions are faster than the corresponding C++ functions (cout, cin, and other streams) is that the latter do typechecking. As this usually involves some requests to overloaded operators, it can take some time.
In fact, in programming competitions it is often recommended that you use printf et al rather than cout/cin for precisely this reason.