Removing '#include algorithm' doesn't break the code
The reason it works is because has been included by a header that you have also included.
For example vector might have included algorithms in it's source. This is common as they are often header only.
That said, you can not rely on the specific implementation of the standard library to have the same includes in each header. (for example with might work with MSVC and it might break with gcc stdlibc+++).
For this reasons I highly recommend including what you use, regardless of where it will compile of not. --- note that this is slightly different to 'what you reference' because forward declaration for point and references in headers can significantly improve build time.
How to remove all the occurrences of a char in c++ string
Basically, replace
replaces a character with another and ''
is not a character. What you're looking for is erase
.
See this question which answers the same problem. In your case:
#include <algorithm>
str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());
Or use boost
if that's an option for you, like:
#include <boost/algorithm/string.hpp>
boost::erase_all(str, "a");
All of this is well-documented on reference websites. But if you didn't know of these functions, you could easily do this kind of things by hand:
std::string output;
output.reserve(str.size()); // optional, avoids buffer reallocations in the loop
for(size_t i = 0; i < str.size(); ++i)
if(str[i] != 'a') output += str[i];
Is it possible for a missing #include to break the program at runtime?
Yes, it's perfectly possible. I'm sure there are lots of ways, but suppose the include file contained a global variable definition which called a constructor. In the first case the constructor would execute, and in the second it wouldn't.
Putting a global variable definition in a header file is poor style, but it's possible.
When to use virtual destructors?
Virtual destructors are useful when you might potentially delete an instance of a derived class through a pointer to base class:
class Base
{
// some virtual methods
};
class Derived : public Base
{
~Derived()
{
// Do some important cleanup
}
};
Here, you'll notice that I didn't declare Base's destructor to be virtual
. Now, let's have a look at the following snippet:
Base *b = new Derived();
// use b
delete b; // Here's the problem!
Since Base's destructor is not virtual
and b
is a Base*
pointing to a Derived
object, delete b
has undefined behaviour:
[In
delete b
], if the static type of the
object to be deleted is different from its dynamic type, the static
type shall be a base class of the dynamic type of the object to be
deleted and the static type shall have a virtual destructor or the
behavior is undefined.
In most implementations, the call to the destructor will be resolved like any non-virtual code, meaning that the destructor of the base class will be called but not the one of the derived class, resulting in a resources leak.
To sum up, always make base classes' destructors virtual
when they're meant to be manipulated polymorphically.
If you want to prevent the deletion of an instance through a base class pointer, you can make the base class destructor protected and nonvirtual; by doing so, the compiler won't let you call delete
on a base class pointer.
You can learn more about virtuality and virtual base class destructor in this article from Herb Sutter.
How do I print out the contents of a vector?
If you have a C++11 compiler, I would suggest using a range-based for-loop (see below); or else use an iterator. But you have several options, all of which I will explain in what follows.
Range-based for-loop (C++11)
In C++11 (and later) you can use the new range-based for-loop, which looks like this:
std::vector<char> path;
// ...
for (char i: path)
std::cout << i << ' ';
The type char
in the for-loop statement should be the type of the elements of the vector path
and not an integer indexing type. In other words, since path
is of type std::vector<char>
, the type that should appear in the range-based for-loop is char
. However, you will likely often see the explicit type replaced with the auto
placeholder type:
for (auto i: path)
std::cout << i << ' ';
Regardless of whether you use the explicit type or the auto
keyword, the object i
has a value that is a copy of the actual item in the path
object. Thus, all changes to i
in the loop are not preserved in path
itself:
std::vector<char> path{'a', 'b', 'c'};
for (auto i: path) {
i = '_'; // 'i' is a copy of the element in 'path', so although
// we can change 'i' here perfectly fine, the elements
// of 'path' have not changed
std::cout << i << ' '; // will print: "_ _ _"
}
for (auto i: path) {
std::cout << i << ' '; // will print: "a b c"
}
If you would like to proscribe being able to change this copied value of i
in the for-loop as well, you can force the type of i
to be const char
like this:
for (const auto i: path) {
i = '_'; // this will now produce a compiler error
std::cout << i << ' ';
}
If you would like to modify the items in path
so that those changes persist in path
outside of the for-loop, then you can use a reference like so:
for (auto& i: path) {
i = '_'; // changes to 'i' will now also change the
// element in 'path' itself to that value
std::cout << i << ' ';
}
and even if you don't want to modify path
, if the copying of objects is expensive you should use a const reference instead of copying by value:
for (const auto& i: path)
std::cout << i << ' ';
Iterators
Before C++11 the canonical solution would have been to use an iterator, and that is still perfectly acceptable. They are used as follows:
std::vector<char> path;
// ...
for (std::vector<char>::const_iterator i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
If you want to modify the vector's contents in the for-loop, then use iterator
rather than const_iterator
.
Supplement: typedef / type alias (C++11) / auto (C++11)
This is not another solution, but a supplement to the above iterator
solution. If you are using the C++11 standard (or later), then you can use the auto
keyword to help the readability:
for (auto i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
Here the type of i
will be non-const (i.e., the compiler will use std::vector<char>::iterator
as the type of i
). This is because we called the begin
method, so the compiler deduced the type for i
from that. If we call the cbegin
method instead ("c" for const), then i
will be a std::vector<char>::const_iterator
:
for (auto i = path.cbegin(); i != path.cend(); ++i) {
*i = '_'; // will produce a compiler error
std::cout << *i << ' ';
}
If you're not comfortable with the compiler deducing types, then in C++11 you can use a type alias to avoid having to type the vector out all the time (a good habit to get into):
using Path = std::vector<char>; // C++11 onwards only
Path path; // 'Path' is an alias for std::vector<char>
// ...
for (Path::const_iterator i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
If you do not have access to a C++11 compiler (or don't like the type alias syntax for whatever reason), then you can use the more traditional typedef
:
typedef std::vector<char> Path; // 'Path' now a synonym for std::vector<char>
Path path;
// ...
for (Path::const_iterator i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
Side note:
At this point, you may or may not have come across iterators before, and you may or may not have heard that iterators are what you are "supposed" to use, and may be wondering why. The answer is not easy to appreciate, but, in brief, the idea is that iterators are an abstraction that shield you from the details of the operation.
It is convenient to have an object (the iterator) that does the operation you want (like sequential access) rather than you writing the details yourself (the "details" being the code that does the actual accessing of the elements of the vector). You should notice that in the for-loop you are only ever asking the iterator to return you a value (*i
, where i
is the iterator) -- you are never interacting with path
directly itself. The logic goes like this: you create an iterator and give it the object you want to loop over (iterator i = path.begin()
), and then all you do is ask the iterator to get the next value for you (*i
); you never had to worry exactly how the iterator did that -- that's its business, not yours.
OK, but what's the point? Well, imagine if getting a value wasn't simple. What if it involves a bit of work? You don't need to worry, because the iterator has handled that for you -- it sorts out the details, all you need to do is ask it for a value. Additionally, what if you change the container from std::vector
to something else? In theory, your code doesn't change even if the details of how accessing elements in the new container does: remember, the iterator sorts all the details out for you behind the scenes, so you don't need to change your code at all -- you just ask the iterator for the next value in the container, same as before.
So, whilst this may seem like confusing overkill for looping through a vector, there are good reasons behind the concept of iterators and so you might as well get used to using them.
Indexing
You can also use a integer type to index through the elements of the vector in the for-loop explicitly:
for (int i=0; i<path.size(); ++i)
std::cout << path[i] << ' ';
If you are going to do this, it's better to use the container's member types, if they are available and appropriate. std::vector
has a member type called size_type
for this job: it is the type returned by the size
method.
typedef std::vector<char> Path; // 'Path' now a synonym for std::vector<char>
for (Path::size_type i=0; i<path.size(); ++i)
std::cout << path[i] << ' ';
Why not use this in preference to the iterator
solution? For simple cases, you can do that, but using an iterator
brings several advantages, which I have briefly outlined above. As such, my advice would be to avoid this method unless you have good reasons for it.
std::copy (C++11)
See Joshua's answer. You can use the STL algorithm std::copy
to copy the vector contents onto the output stream. I don't have anything to add, except to say that I don't use this method; but there's no good reason for that besides habit.
std::ranges::copy (C++20)
For completeness, C++20 introduced ranges, which can act on the whole range of a std::vector
, so no need for begin
and end
:
#include <iterator> // for std::ostream_iterator
#include <algorithm> // for std::ranges::copy depending on lib support
std::vector<char> path;
// ...
std::ranges::copy(path, std::ostream_iterator<char>(std::cout, " "));
Unless you have a recent compiler (on GCC apparently at least version 10.1), likely you will not have ranges support even if you might have some C++20 features available.
Overload std::ostream::operator<<
See also Chris's answer below. This is more a complement to the other answers since you will still need to implement one of the solutions above in the overloading, but the benefit is much cleaner code. This is how you could use the std::ranges::copy
solution above:
#include <iostream>
#include <vector>
#include <iterator> // for std::ostream_iterator
#include <algorithm> // for std::ranges::copy depending on lib support
using Path = std::vector<char>; // type alias for std::vector<char>
std::ostream& operator<< (std::ostream& out, const Path& v) {
if ( !v.empty() ) {
out << '[';
std::ranges::copy(v, std::ostream_iterator<char>(out, ", "));
out << "\b\b]"; // use two ANSI backspace characters '\b' to overwrite final ", "
}
return out;
}
int main() {
Path path{'/', 'f', 'o', 'o'};
// will output: "path: [/, f, o, o]"
std::cout << "path: " << path << std::endl;
return 0;
}
Now you can pass your Path
objects to your output stream just like fundamental types. Using any of the other solutions above should also be equally straightforward.
Conclusion
Any of the solutions presented here will work. It's up to you (and context or your coding standards) on which one is the "best". Anything more detailed than this is probably best left for another question where the pros/cons can be properly evaluated, but as always user preference will always play a part: none of the solutions presented are objectively wrong, but some will look nicer to each coder.
Addendum
This is an expanded solution of an earlier one I posted. Since that post kept getting attention, I decided to expand on it and refer to the other excellent solutions posted here, at least those that I have personally used in the past at least once. I would, however, encourage the reader to look at the answers below because there are probably good suggestions that I have forgotten, or do not know, about.
Including exception header C++
You should always follow documentation. When documentation says that in order to use ceratain construct you need to include certain header, the header must be included. Otherwise, tomorrow iostream
will stop including the header, and your program will fail to compile or worse - will behave unexpectedly.
Is std::vector so much slower than plain arrays?
Using the following:
g++ -O3 Time.cpp -I <MyBoost>
./a.out
UseArray completed in 2.196 seconds
UseVector completed in 4.412 seconds
UseVectorPushBack completed in 8.017 seconds
The whole thing completed in 14.626 seconds
So array is twice as quick as vector.
But after looking at the code in more detail this is expected; as you run across the vector twice and the array only once. Note: when you resize()
the vector you are not only allocating the memory but also running through the vector and calling the constructor on each member.
Re-Arranging the code slightly so that the vector only initializes each object once:
std::vector<Pixel> pixels(dimensions * dimensions, Pixel(255,0,0));
Now doing the same timing again:
g++ -O3 Time.cpp -I <MyBoost>
./a.out
UseVector completed in 2.216 seconds
The vector now performance only slightly worse than the array. IMO this difference is insignificant and could be caused by a whole bunch of things not associated with the test.
I would also take into account that you are not correctly initializing/Destroying the Pixel object in the UseArrray()
method as neither constructor/destructor is not called (this may not be an issue for this simple class but anything slightly more complex (ie with pointers or members with pointers) will cause problems.
Deleting last element in a std::vector of std::shared_ptr while iterating over it causes segmentation fault
Change:
v.erase(el_it);
To
el_it = v.erase(el_it); // don't do this yet, read below
Erasing invalidates iterators. The return value of erase is the valid iterator to the next element. So with what I wrote above you're skipping one element. I'd recommend this:
for (auto el_it = v.begin(); el_it != v.end();) {
auto el = *el_it;
if (el->age_ == 2) {
el_it = v.erase(el_it);
} else {
++ el_it;
}
}
Related Topics
Is There a Standard Date/Time Class in C++
Overload Resolution with Std::Function
Inconsistent Strcmp() Return Value When Passing Strings as Pointers or as Literals
Does Copy List Initialization Invoke Copy Ctor Conceptually
How to Convert from Lpctstr to Std::String
Difference Between Regex_Match and Regex_Search
Covariant Return Type and Type Conversion
Can't Open Txt Files in C++ Program with Visual Studio 2019
What Is the Purpose of the "Final" Keyword in C++11 for Functions
Svm Classifier Based on Hog Features for "Object Detection" in Opencv
How to Tell Reliably If a Boost Thread Has Exited Its Run Method
Segmentation Fault with Char Array and Pointer in C on Linux
Does Clearing a Vector Affect Its Capacity
C++ Templates: Conditionally Enabled Member Function
Portable End of Line (Newline)
How to Legally Reinterpret_Cast Between Layout-Compatible Standard-Layout Types