- <cassert> (assert.h)
- <cctype> (ctype.h)
- <cerrno> (errno.h)
- C++11 <cfenv> (fenv.h)
- <cfloat> (float.h)
- C++11 <cinttypes> (inttypes.h)
- <ciso646> (iso646.h)
- <climits> (limits.h)
- <clocale> (locale.h)
- <cmath> (math.h)
- <csetjmp> (setjmp.h)
- <csignal> (signal.h)
- <cstdarg> (stdarg.h)
- C++11 <cstdbool> (stdbool.h)
- <cstddef> (stddef.h)
- C++11 <cstdint> (stdint.h)
- <cstdio> (stdio.h)
- <cstdlib> (stdlib.h)
- <cstring> (string.h)
- C++11 <ctgmath> (tgmath.h)
- <ctime> (time.h)
- C++11 <cuchar> (uchar.h)
- <cwchar> (wchar.h)
- <cwctype> (wctype.h)
- C++11 <array>
- C++11 <forward_list>
- C++11 <unordered_map>
- C++11 <unordered_set>
- C++11 <atomic>
- C++11 <condition_variable>
- C++11 <future>
- C++11 <mutex>
- C++11 <thread>
- C++11 <chrono>
- C++11 <codecvt>
- C++11 <initializer_list>
- C++11 <random>
- C++11 <ratio>
- C++11 <regex>
- C++11 <system_error>
- C++11 <tuple>
- C++11 <type_traits>
- C++11 <typeindex>
- C++11 begin
- C++11 make_move_iterator
- C++11 move_iterator
Template parameters, member types, member functions.
Iterators are a generalization of pointers that allow a C++ program to work with different data structures (for example, containers and ranges (since C++20) ) in a uniform manner. The iterator library provides definitions for iterators, as well as iterator traits, adaptors, and utility functions.
Since iterators are an abstraction of pointers, their semantics are a generalization of most of the semantics of pointers in C++. This ensures that every function template that takes iterators works as well with regular pointers.
[ edit ] Iterator categories
There are five (until C++17) six (since C++17) kinds of iterators: LegacyInputIterator , LegacyOutputIterator , LegacyForwardIterator , LegacyBidirectionalIterator , LegacyRandomAccessIterator , and LegacyContiguousIterator (since C++17) . (See also LegacyIterator for the most basic kind of iterator.)
Instead of being defined by specific types, each category of iterator is defined by the operations that can be performed on it. This definition means that any type that supports the necessary operations can be used as an iterator -- for example, a pointer supports all of the operations required by LegacyRandomAccessIterator , so a pointer can be used anywhere a LegacyRandomAccessIterator is expected.
All of the iterator categories (except LegacyOutputIterator ) can be organized into a hierarchy, where more powerful iterator categories (e.g. LegacyRandomAccessIterator ) support the operations of less powerful categories (e.g. LegacyInputIterator ). If an iterator falls into one of these categories and also satisfies the requirements of LegacyOutputIterator , then it is called a mutable iterator and supports both input and output. Non-mutable iterators are called constant iterators.
- ↑ LegacyContiguousIterator category was only formally specified in C++17, but the iterators of std::vector , std::basic_string , std::array , and std::valarray , as well as pointers into C arrays are often treated as a separate category in pre-C++17 code.
Note: A type supporting the required operations in a row of the table above does not necessarily fall into the corresponding category, see the category page for the complete list of requirements.
[ edit ] Definitions
[ edit ] types and writability.
An input iterator i supports the expression * i , resulting in a value of some object type T , called the value type of the iterator.
An output iterator i has a non-empty set of types that are writable (until C++20) indirectly_writable (since C++20) to the iterator; for each such type T , the expression * i = o is valid where o is a value of type T .
For every iterator type X for which equality is defined (until C++20) , there is a corresponding signed integer (until C++20) integer-like (since C++20) type called the difference type of the iterator.
[ edit ] Dereferenceability and validity
Just as a regular pointer to an array guarantees that there is a pointer value pointing past the last element of the array, so for any iterator type there is an iterator value that points past the last element of a corresponding sequence. Such a value is called a past-the-end value.
Values of an iterator i for which the expression * i is defined are called dereferenceable . The standard library never assumes that past-the-end values are dereferenceable.
Iterators can also have singular values that are not associated with any sequence. Results of most expressions are undefined for singular values; the only exceptions are
- the assignment of a non-singular value to an iterator that holds a singular value,
- destroying an iterator that holds a singular value, and,
- for iterators that meet the DefaultConstructible requirements, using a value-initialized iterator as the source of a copy or move (since C++11) operation.
In these cases the singular value is overwritten the same way as any other value. Dereferenceable values are always non-singular.
An invalid iterator is an iterator that may be singular.
[ edit ] Ranges
Most of the standard library’s algorithmic templates that operate on data structures have interfaces that use ranges.
The result of the application of functions in the standard library to invalid ranges is undefined.
[ edit ] Iterator concepts
C++20 introduces a new system of iterators based on concepts that are different from C++17 iterators. While the basic taxonomy remains similar, the requirements for individual iterator categories are somewhat different.
[ edit ] Iterator associated types
[ edit ] iterator primitives, [ edit ] iterator customization points, [ edit ] algorithm concepts and utilities.
C++20 also provides a set of concepts and related utility templates designed to ease constraining common algorithm operations.
[ edit ] Iterator adaptors
[ edit ] stream iterators, [ edit ] iterator operations, [ edit ] range access.
These non-member functions provide a generic interface for containers, plain arrays, and std::initializer_list .
[ edit ] Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
- Recent changes
- Offline version
- What links here
- Related changes
- Upload file
- Special pages
- Printable version
- Permanent link
- Page information
- In other languages
- This page was last modified on 1 September 2023, at 23:42.
- This page has been accessed 948,884 times.
- About cppreference.com
21.3 — STL iterators overview
An Iterator is an object that can traverse (iterate over) a container class without the user having to know how the container is implemented. With many classes (particularly lists and the associative classes), iterators are the primary way elements of these classes are accessed.
An iterator is best visualized as a pointer to a given element in the container, with a set of overloaded operators to provide a set of well-defined functions:
- Operator* -- Dereferencing the iterator returns the element that the iterator is currently pointing at.
- Operator++ -- Moves the iterator to the next element in the container. Most iterators also provide Operator-- to move to the previous element.
- Operator== and Operator!= -- Basic comparison operators to determine if two iterators point to the same element. To compare the values that two iterators are pointing at, dereference the iterators first, and then use a comparison operator.
- Operator= -- Assign the iterator to a new position (typically the start or end of the container’s elements). To assign the value of the element the iterator is pointing at, dereference the iterator first, then use the assign operator.
Each container includes four basic member functions for use with Operator=:
- begin() returns an iterator representing the beginning of the elements in the container.
- end() returns an iterator representing the element just past the end of the elements.
- cbegin() returns a const (read-only) iterator representing the beginning of the elements in the container.
- cend() returns a const (read-only) iterator representing the element just past the end of the elements.
It might seem weird that end() doesn’t point to the last element in the list, but this is done primarily to make looping easy: iterating over the elements can continue until the iterator reaches end(), and then you know you’re done.
Finally, all containers provide (at least) two types of iterators:
- container::iterator provides a read/write iterator
- container::const_iterator provides a read-only iterator
Lets take a look at some examples of using iterators.
Iterating through a vector
This prints the following:
Iterating through a list
Now let’s do the same thing with a list:
Note the code is almost identical to the vector case, even though vectors and lists have almost completely different internal implementations!
Iterating through a set
In the following example, we’re going to create a set from 6 numbers and use an iterator to print the values in the set:
This program produces the following result:
Note that although populating the set differs from the way we populate the vector and list, the code used to iterate through the elements of the set was essentially identical.
Iterating through a map
This one is a little trickier. Maps and multimaps take pairs of elements (defined as a std::pair). We use the make_pair() helper function to easily create pairs. std::pair allows access to the elements of the pair via the first and second members. In our map, we use first as the key, and second as the value.
This program produces the result:
Notice here how easy iterators make it to step through each of the elements of the container. You don’t have to care at all how map stores its data!
Iterators provide an easy way to step through the elements of a container class without having to understand how the container class is implemented. When combined with STL’s algorithms and the member functions of the container classes, iterators become even more powerful. In the next lesson, you’ll see an example of using an iterator to insert elements into a list (which doesn’t provide an overloaded operator to access its elements directly).
One point worth noting: Iterators must be implemented on a per-class basis, because the iterator does need to know how a class is implemented. Thus iterators are always tied to specific container classes.
C++ : STL: Iterators for vector
Iterating over a vector with subscripts.
Passing over all the elements of a vector is simple, and is usually done using subscripts instead of an iterator. The main advantage of an iterator is that it can be used by many of the functions in <algorithms>. Subscripts provide an easy, familiar way to access vector elements in much the way that array elements would be accessed.
Iterators are similar to pointers
Iterating over a vector with an iterator, why use iterators when subscripts work so well.
- Not always possible . Subscripts can not be used on most of the containers (eg, list and map ), so you must use iterators in many cases.
- Flexible . It is easily to change underlying container types. For example, you might decide later that the number of insertions and deletions is so high that a list would be more efficient than a vector .
- Member functiuons . Many of the member functions for vector use iterators, for example, assign , insert , or erase .
- Algorithms . The <algorithm> functions use iterators.
Ways to iterate over Vector in C++ STL
C++ software engineering.
Get this book -> Problems on Array: For Interviews and Competitive Programming
In this article, we have explored different ways to iterate over Vector in C++ STL. These include techniques like indexing, iterators, range based for loop and much more.
Vectors are sequence conatiners similar to dynamic arrays. Vectors have ability to resize themselves. The dat in vectors are stored in contigous fashion. Hence the data can not only be accessed through iterators and but also through indices .
When we write code in C++ we are in a constant dilemma in which way we should iterate over a collection. Obviously it depends on the type of data structure we are trying to iterte over. But, most of them anyway follow the same structure. Now we will see various ways to iterate over a vector in C++ STL. Then we will try to print out the contents of array using the ways that we explore.
The Different Ways to iterate over Vector in C++ STL are:
Iterate using Indexing
Using iterators, using range based for loop, using std::for_each.
Using indexing is the textbook way for iterating over a vector using normal loops. It allows us to know the exact index position of the elements that we are accessing. The for loop can be used to access the vector from one postion to a latter position.
- initialize and populate a vector
- loop from i = 0 to size of vector
- do print element of vector at index i
- Some people might hesistate to use this code due to calling of vector::size on each iteration however it has constant time complexity hence it is nothing to wory about
- Worst case time complexity: Θ(n)
- Average case time complexity: Θ(n)
- Best case time complexity: Θ(n)
- Space complexity: Θ(1)
- This method can be helpful when you need to use the index (eg. accessing next/previous element, using the index iside the loop)
- This method is also great when you need a stride other than 1 this can be changed by replacing updation part of for loop with something like i += 2 for accessing only alternate elements.
Iterators are used to iterate over a collection of data. When we think of iterators we use usually think of collection of data and ways to iterate over it. Using vector::begin() and vector::end() allow us to access pointers to start and end of vector respectively. Also vector::rbegin() and vector::rend() can also be used in similar fashion.
- loop from iter = vector beginning to vector end
- inside the loop you can access individual elements by dereferencing iter
- vector::begin() and vector::end() have complexity of Θ(1) hence they do not affect the time complexity.
- Similar to usind indeces here also we can control the stride in a similar fashion to what was discussed earlier.
- Using iterators gives us a significant advantage: it allows abstraction. It will enable us to write generic code that can be used with various containers and not necessarily be limited to only vectors, making our code more reusable.
Range-based for loops were introduced in C++11 and executes for loop over a range. Range-based for loops help to make our code more readable. It provides an elegant and clean way to access the elements. Once you look at the code, it might look like sorcery to you, but under the hood, it is using the logic that we saw above.
for ( declaration : range ) loop expression
- declaration is a variable of the same type as data type of the vector that is assigned values
- range is the expression that shows the range the for loop is to be run over
- loop expression here refers to the loop body
- If you dont need to access the index and dont need to iterate over the vector in a particular order. RAnge based for loops make our code easier to understand
- when we need to iterate the whole vector these help us write less verbose.
Apart from the generic looping algorithms namely for loop, while loops and do while loop. for_each allows us to iterate over an array or collection and execute an block of statements over each element of the collection.
- Initialise and populate a vector
- for_each( begin, end, statements)
begin signifies the start of the range end signifies end of range statements refer to functions to be performed on each element
- Worst case time complexity: Θ(nx)
- Average case time complexity: Θ(nx)
- Best case time complexity: Θ(nx)
- Space complexity: Θ(ny)
- Here x is best/average/worst case time complexity of statements
- Here y is space complexity of the statements
For single code use markdown as follows:
- It is generic and hence not limited to one type of container hence swapping the type of container it iterates on is painless
- Allows us to apply side-effects on function object.
Which functionality was added in C++ 11 that aimed to reduce unnecessary verbose
What allows us to perform a block of statements on elements of vector by passing function objects by refernece, what is(are) disadvantages of range based for loop.
- Standard Template Library
- STL Vectors
- STL Priority Queue
- STL Multiset
- STL Multimap
- STL Unordered Set
- STL Unordered Map
- STL Unordered Multiset
- STL Unordered Multimap
- STL Iterators
- STL Algorithm
- Write an Interview Experience
- Share Your Campus Experience
Vector in C++ STL
- Initialize a vector in C++ (7 different ways)
Commonly Used Methods
- vector::begin() and vector::end() in C++ STL
- vector::empty() and vector::size() in C++ STL
- vector::operator= and vector::operator[ ] in C++ STL
- vector::front() and vector::back() in C++ STL
- vector::push_back() and vector::pop_back() in C++ STL
- vector insert() Function in C++ STL
- vector emplace() function in C++ STL
- vector :: assign() in C++ STL
- vector erase() and clear() in C++
Other Member Methods
- vector max_size() function in C++ STL
- vector capacity() function in C++ STL
- vector rbegin() and rend() function in C++ STL
- vector :: cbegin() and vector :: cend() in C++ STL
- vector::crend() & vector::crbegin() with example
- vector : : resize() in C++ STL
- vector shrink_to_fit() function in C++ STL
- Using std::vector::reserve whenever possible
- vector data() function in C++ STL
- 2D Vector In C++ With User Defined Size
- Passing Vector to a Function in C++
- How does a vector work in C++?
- How to implement our own Vector Class in C++?
- Advantages of vector over array in C++
Common Vector Programs
- Sorting a vector in C++
- How to reverse a Vector using STL in C++?
- How to find the minimum and maximum element of a Vector using STL in C++?
- How to find index of a given element in a Vector in C++
Vectors are the same as dynamic arrays with the ability to resize itself automatically when an element is inserted or deleted, with their storage being handled automatically by the container. Vector elements are placed in contiguous storage so that they can be accessed and traversed using iterators. In vectors, data is inserted at the end. Inserting at the end takes differential time, as sometimes the array may need to be extended. Removing the last element takes only constant time because no resizing happens. Inserting and erasing at the beginning or in the middle is linear in time.
What is std::vector in C++?
std::vector in C++ is the class template that contains the vector container and its member functions. It is defined inside the <vector> header file. The member functions of std::vector class provide various functionalities to vector containers. Some commonly used member functions are written below:
- begin() – Returns an iterator pointing to the first element in the vector
- end() – Returns an iterator pointing to the theoretical element that follows the last element in the vector
- rbegin() – Returns a reverse iterator pointing to the last element in the vector (reverse beginning). It moves from last to first element
- rend() – Returns a reverse iterator pointing to the theoretical element preceding the first element in the vector (considered as reverse end)
- cbegin() – Returns a constant iterator pointing to the first element in the vector.
- cend() – Returns a constant iterator pointing to the theoretical element that follows the last element in the vector.
- crbegin() – Returns a constant reverse iterator pointing to the last element in the vector (reverse beginning). It moves from last to first element
- crend() – Returns a constant reverse iterator pointing to the theoretical element preceding the first element in the vector (considered as reverse end)
- size() – Returns the number of elements in the vector.
- max_size() – Returns the maximum number of elements that the vector can hold.
- capacity() – Returns the size of the storage space currently allocated to the vector expressed as number of elements.
- resize(n) – Resizes the container so that it contains ‘n’ elements.
- empty() – Returns whether the container is empty.
- shrink_to_fit() – Reduces the capacity of the container to fit its size and destroys all elements beyond the capacity.
- reserve() – Requests that the vector capacity be at least enough to contain n elements.
- reference operator [g] – Returns a reference to the element at position ‘g’ in the vector
- at(g) – Returns a reference to the element at position ‘g’ in the vector
- front() – Returns a reference to the first element in the vector
- back() – Returns a reference to the last element in the vector
- data() – Returns a direct pointer to the memory array used internally by the vector to store its owned elements.
- assign() – It assigns new value to the vector elements by replacing old ones
- push_back() – It push the elements into a vector from the back
- pop_back() – It is used to pop or remove elements from a vector from the back.
- insert() – It inserts new elements before the element at the specified position
- erase() – It is used to remove elements from a container from the specified position or range.
- swap() – It is used to swap the contents of one vector with another vector of same type. Sizes may differ.
- clear() – It is used to remove all the elements of the vector container
- emplace() – It extends the container by inserting new element at position
- emplace_back() – It is used to insert a new element into the vector container, the new element is added to the end of the vector
The time complexity for doing various operations on vectors is-
- Random access – constant O(1)
- Insertion or removal of elements at the end – constant O(1)
- Insertion or removal of elements – linear in the distance to the end of the vector O(N)
- Knowing the size – constant O(1)
- Resizing the vector- Linear O(N)
All Vector Functions:
Please Login to comment...
Improve your Coding Skills with Practice
- Stack Overflow Public questions & answers
- Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
- Talent Build your employer brand
- Advertising Reach developers & technologists worldwide
- Labs The future of collective knowledge sharing
- About the company
Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Is using begin() and end() of an empty std::vector well defined?
Presume that I am copying a std::vector into a std::vector with std::vector::insert (as below).
The question is: when the vector that I am copying from is empty, are begin() and end() well defined in all circumstances for purposes of the std::vector::insert call?
The reason I ask is this sentence:
If allocator_traits::construct is not supported with the appropriate arguments for the element constructions, or if an invalid position or range is specified, it causes undefined behavior.
- 4 yes, begin() and end() are well-defined for empty vectors (and will test equal in that case). The end of a vector (empty or not) is a valid insert position – M.M Aug 27 at 21:53
- Yes. begin() and end() are well defined for an empty vector. They will compare equal (so, for example, range-based loops won't execute the body at all) and you should avoid dereferencing either of them (as doing so will access a non-existent element). Inserting is fine. – Peter Aug 28 at 2:21
2 Answers 2
Firstly, begin() and end() always work. We know this because std::vector satisfies the Container requirement, and begin() is defined as follows:
b.begin() Result : iterator ; const_iterator for constant b . Returns : An iterator referring to the first element in the container. Complexity : Constant.
This function has no preconditions, so it must always work, even for empty, and even for moved-from vectors.
Furthermore, all calls to insert you're making are well-defined because the requirements for a SequenceContainer in [sequence.reqmts] (which std::vector satisfies) require only the following for insert(p, i, j) , where p , i , j are iterators:
a.insert(p, i, j) Result : iterator . Preconditions : [Type constraints.] Neither i nor j are iterators into a . [...]
Namely, it's not required by insert that [i, j) is a non-empty range.
On a side note, cplusplus.com is massively out-of-date in a lot of cases. cppreference.com is more actively maintained, though it's sometimes wrong and incomplete. When in doubt, refer directly to the C++ standard.
- There have been issues in the past with begin/end returning a null pointer in this case, and the caller passing that to memcpy, which does not support null pointer arguments. Something to be aware of. – Marc Glisse Aug 28 at 7:31
- @MarcGlisse that's a good point. I wonder though, since std::vector::begin() isn't required to be a pointer, wouldn't you normally use data() for memcpy ? – Jan Schultke Aug 28 at 10:13
- If you are passing it directly to memcpy, yes, data() is more relevant indeed. But if you are passing it to std::copy or some other standard function that may be specialized to call memcpy for some types of iterators... (the issue was thus probably a bug in those standard library implementations and has thus likely been fixed a while ago) so maybe my comment wasn't that relevant. – Marc Glisse Aug 28 at 11:47
Yes, they are. Empty range (i.e., one where first == last ) is a valid range. An example of invalid range would be one where first and last iterators are not from the same container, one or both iterators are invalidated or if they came from the same container as you try to insert into.
Personally, I wouldn't use cplusplus.com, it's very outdated. And the way they explain things doesn't seem clear either (as seen by your question). Use cppreference instead.
- cplusplus.com is clearly laid out and has always about perfect balance between informative and succinct. It is "to the point". cppreference.com on the other hand appears bloated, has way too much information and oftentimes is a difficult read. Now I know this latter site is up to date while the former site is not, but for everything up to C++14 I find cplusplus.com a preferable reference. – Giogre Aug 27 at 22:07
- 1 cplusplus.com thinks C++11 is the latest and greatest, and is incomplete for C++11, C++14, and it doesn't even know anything else exists. It is exactly because it is out of date that it is a garbage reference. You literally can't know if you're missing anything. Like a modal text editor, cppreference takes time to get accustomed with, but once you do, it's fantastic. – sweenish Aug 27 at 22:25
- 1 @Giogre I stand by my opinion. Given that C++14 is a decade old now, I do find it obsolete. I couldn't use it to get information for work for example. And I find several parts of cplusplus formatting just bad. Like, when they decide to put several constructors on one line and dump a lot of spaces in for whatever reason: cplusplus.com/reference/vector/vector/vector . Cprreference may be giving out too much information at times, but at least it's complete and correct information. Not the reference's fault that C++ is a difficult language. – Yksisarvinen Aug 27 at 22:27
- The legacy version of cplusplus.com is correctly formatted legacy.cplusplus.com/reference/vector/vector/vector Sadly, what update they introduced, the new graphic layout a couple of years ago, is more a degradation than an enhancement. I don't know why the author stop updating the site 10 years ago. Same reason Scott Meyers "retired" from C++? – Giogre Aug 27 at 22:36
Sign up or log in, post as a guest.
Required, but never shown
Not the answer you're looking for? Browse other questions tagged c++ stdvector or ask your own question .
- Featured on Meta
- Our Design Vision for Stack Overflow and the Stack Exchange network
- Call for volunteer reviewers for an updated search experience: OverflowAI Search
- Discussions experiment launching on NLP Collective
- Temporary policy: Generative AI (e.g., ChatGPT) is banned
Hot Network Questions
- Is the response "It's 10 minutes walking" correct and natural?
- Mount drive not as removable drive
- expl3: vlists, galleys, boxes and coffins: what they are and how they interact
- Wrongly got exit stamp from Schengen zone
- Did Romans complain about sundials?
- What typical percentage current is required to hold a standard non-latching reed relay/contactor shut?
- Golf the fast growing hierarchy
- Can we prevent a command from being executed for root in Linux?
- Did the Z8000 ever hit the home computer market?
- A burnt-out 15A receptacle is wired into a 60A circuit. What can I do?
- Are there any good alternatives to firearms for 1920s aircrafts?
- Required ancilla qubits for a given function's oracle
- Does every sequence of group epimorphisms (between finitely generated groups) contain a stable subsequence?
- In a multilingual app, can we use only english for titles, alt etc
- QGIS - Add WMS layer with extra parameters
- Is assigning a probability to uncertainty a contradiction?
- How to describe the location (North, South, East and West) of country/city with respect to other country/city (in German language)
- What disrespectful connotations does "redline" have?
- Was the U.S. surprised about the Huawei breakthrough, how much time did the government or think-tanks expect China to take to produce a 7nm chip?
- Meaning of "retiring" in "free admission with retiring donations"
- Restrict sorting to a certain range
- Can a company call me back from a garden leave?
- A Trivial Pursuit #01 (Geography 1/4): History
- How to draw a bar-in-bar chart using Mathematica? or align two bar/rectangle charts at the center of the bar rather than the left alignment?
Go for C++ developers: A beginner's guide
After years of working on software written in C and C++ , I switched to working on a project that is implemented in Go . More developers may find themselves working in the Go ecosystem as more software, such as Red Hat OpenShift and Kubernetes , is implemented in Go. This article discusses the primary language differences between Go and C++, differences in the development environments, and differences in the program-building environment. Examples and code snippets are from the Grafana sources.
Go statements are terminated by a semicolon. Go treats the end of a non-blank line as a semicolon unless it can be determined that the line is incomplete. As a result, go requires the opening brace to be on the same line as the function definition:
Go requires the closing then brace to be on the same line as the else :
Variable and type declaration
Go declarations start with the keyword var followed by the name and then the type, which is the opposite of C. A series of declarations may be placed in parentheses.
A variable may be initialized when it is declared. If the type is not specified, the variable type will be the type of the initialization expression. var msg = "unknown" which will define msg as a string.
A short declaration syntax is allowed within a function or loop. One or more variables may be defined this way. If multiple variables are defined using this method, then one of the variables may have already been declared. This is often used to define and use an error variable.
A type declaration defines a new named type. A common use is to create a type for a defined structure.
Go has a blank identifier, which causes the return value of the right side of the assignment to be ignored.
Go permits multiple assignments, which are done in parallel.
Any declared but not explicitly initialized variable is automatically initialized to the zero value of the type: false for booleans, 0 for numeric types,"" for strings, and nil for other types. A variable must either be initialized or the type must be specified.
Go, unlike C++, requires that two variables can only be compared or assigned if their type definitions match. Go does not support implicit type conversion.
Go constants can be typed or untyped. If the type is present, then the expressions must be assignable to that type. If the type is omitted, the constant takes the type of the expression. An untyped numeric constant represent values using arbitrary precision.
Go does not support enums. Instead, you can use the special name iota in a constant declaration that represents successive untyped integer constants.
Arrays in Go are first-class values. When an array is used as a function parameter, the function receives a copy of the array, not a pointer to it. However, in practice, functions often use slices for parameters; slices hold pointers to underlying arrays.
A slice can be understood to be a struct with three fields: an array pointer, a length, and a maximum size. Slices use the  operator to access elements of the underlying array. The len function returns the length of the slice, and the cap function returns the maximum size.
Given an array or another slice, a new slice is created via:
where newarr starts at index i and ends prior to index j. newarr refers to arr , thus changes made to newarr are reflected in arr . An array pointer can be assigned to a variable of slice type:
A slice is similar to std::vector in C++.
Hash tables are provided by the language. They are called maps. A map is an unordered collection of key-value pairs where the keys are unique. It is written as map[key_type]value_type, where key_type is the type of the map key and value_type is the type of the map value.
A Go map is similar to std::unordered_map in C++.
Strings are provided by the language. They are immutable and cannot be changed once they have been created.
The for statement is the only looping construct in Go. It may be used with a single condition, which is equivalent to a while statement, or the condition can be omitted, which is an endless loop. Parenthesis are not required:
A for statement can also iterate through the entries of an array, slice, string, or map:
The blank identifier _ is an anonymous placeholder which indicates that the first value returned by range, the index, is ignored. Go permits break and continue to specify a label. The label must refer to a for , switch , or select statement.
In a switch statement, case labels do not fall through. You can make them fall through using the fallthrough keyword. A case may have multiple values. The case value need not be an integer; it can be any type that supports equality comparisons.
The increment and decrement operators may only be used in statements, not in expressions.
Go has pointers but not pointer arithmetic. You cannot use a pointer variable to walk through the bytes of a string. Go uses nil for invalid pointers, where C++ uses NULL or simply 0 .
A function in Go is defined with the func keyword. Input and output parameters are defined separately. There can be multiple return types. In the following example, name is an input string parameter. The function returns two strings.
The return values can be returned by name. For example, in the above:
Parameters are passed by value except for maps and slices, which are passed by reference. The defer statement can be used to call a function after the function containing the defer statement returns.
This is typically used to handle cleanup, such as closing files before the containing function returns. A function definition without a corresponding function name is an anonymous function, as shown in the previous example. The anonymous function can reference variables in the containing function's scope.
Each variable in Go exists as long as there are references to the variable. Go uses garbage collection to free the variable's memory when there are no longer references to it. The memory cannot be released explicitly. The garbage collection is intended to be incremental and efficient on modern processors.
Go uses interfaces in situations where C++ uses classes, subclasses, and templates. A Go interface is similar to a C++ pure abstract class: a class with pure virtual methods and no data members. Go allows any type that provides the methods named in the interface to be treated as an implementation of the interface.
A method definition is similar to a function definition with the addition of a receiver, which is similar to the this pointer in a C++ class method.
fileExpander implements the Expander interface by defining a SetupExpander and Expand method. Any function that takes Expander as a parameter will accept a variable of type fileExpander . If we think of fileExpander as a C++ pure abstract base class, then defining SetupExpander and Expand for fileExpander made it inherit from Expander . A type may satisfy multiple interfaces.
An anonymous field can be used to implement something resembling a C++ child class:
This implements myExpanderType as a child of Expander that inherits its methods.
A variable that has an interface type may be converted to have a different interface type using a special construct called a type assertion. This is implemented dynamically at run time, like C++ dynamic cast. Unlike dynamic cast, there does not need to be any declared relationship between the two interfaces. This is typically used in a type switch, which switches based on the type of value:
Go permits starting a new thread of execution, known as a goroutine, using the go statement. The function runs in a different, newly created goroutine, which shares the address space with the parent. The Go runtime schedules an arbitrary number of goroutines onto a random number of OS threads. Goroutines are more lightweight than OS threads, use a smaller stack, and are scheduled by a userspace runtime scheduler.
Go statements frequently use function literals:
Channels are used to communicate between goroutines. Any value may be sent over a channel. Channels are efficient and cheap. To send a value on a channel, use <- as a binary operator. To receive a value on a channel, use <- as a unary operator. When calling functions, channels are passed by reference. A channel can control access to a single value.
Go provides dependency management, interface abstraction, and documentation tools to assist with programming in the large.
The go command provides various tools for managing the Go development environment:
- go help gives an overview of the go command.
- go env displays the environment variables that define the Go environment.
- The Go compiler and tools are installed into the value displayed by GOROOT.
- gofmt is a tool that enforces layout rules. Most Go code has been run through gofmt . It enforces a single standard Go style.
Go does not use header files. Instead, each source file is a member of a set of related files that form a module. Go has tools to manage versions of modules. Executables created by go are typically statically linked; thus the referenced modules are statically linked.
When a package defines an object (type, constant, variable, function) with a name starting with an upper case letter, that object is visible to any other file that imports that package. Exported names and functions form a module application binary interface, which should not be changed or removed within a major release so that compatibility is maintained.
The environment variable GOPATH , which is typically $HOME/go and can be displayed by go env , contains a directory: pkg where compiled package files are stored based on import statements. Go downloads modules into the directory $GOMODCACHE ; the default path is pkg/mod .
go mod init creates a new go.mod file, which defines the module contents in the current directory. If after creating go.mod we create a simple Go program:
go mod init example.com/test creates a go.mod that describes a module's characteristics.
go mod edit modifies the attributes in go.mod .
go mod tidy will download any modules that our module is importing.
go run . will build and execute a Go program.
go build . will build a Go program
./test abc def [efg hij]
Go provides a test infrastructure. To add a module test, create a program MOD_test.go , where MOD is the module name. The program imports "testing." Each test routine is called Test where Testfoo is an individual test name. t.Fatalf is called if the test fails.
Go is an easy-to-learn language with a large ecosystem of tools. This article gives a C++ programmer the fundamentals to start using Go effectively.
- Red Hat Enterprise Linux
- Red Hat OpenShift
- Red Hat Ansible Automation Platform
- See all products
- See all technologies
- Developer Sandbox
- Developer Tools
- Interactive Tutorials
- API Catalog
- Operators Marketplace
- Learning Resources
- Cheat Sheets
- Contact sales
- Find a partner
- Site Status Dashboard
- Report a security problem
RED HAT DEVELOPER
Build here. Go anywhere.
We serve the builders. The problem solvers who create careers with code.
Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.
We’ve updated our Privacy Statement effective July 1, 2023
Red Hat legal and privacy links
- About Red Hat
- Contact Red Hat
- Red Hat Blog
- Diversity, equity, and inclusion
- Cool Stuff Store
- Red Hat Summit
- Privacy statement
- All policies and guidelines
- Digital accessibility