Sie sind auf Seite 1von 7

A Comparison of C++ and Swift

Jacob Brazeal
Bob Jones University
1700 Wade Hampton Blvd
Greenville, SC 29614
ABSTRACT benchmarks [7] and supports more platforms. We argue that Swift
We find that Swift is typically more readable and reliable than C++, is the better language for its domain – apps in Apple’s ecosystem –
but these design choices sometimes reduce its writability. We find but is too focused to completely displace C++.
that Swift is the superior programming language in the context of The paper is organized as follows: we provide an overview of
the Apple ecosystem, but is not yet ready to replace C++ in general. the structure and syntax of Swift and describe its processor. Then
follows the section Language Features, where we compare and con-
trast Swift’s data types, variables, expressions, control statements,
1 INTRODUCTION subroutines, and generics with comparable features in C++; and
When, in the course of technical frustrations, it becomes necessary last is our conclusion.
to design a new programming language, the designer(s) must bal-
ance a host of competing goals. How important is speed? What 2 OVERVIEW
about ease of writing new code, or portability? One metric for
In this section, we compare and contrast the structure and basic
evaluating a language is the three R’s of programming language
syntax of C++ and Swift, walk through a sample program in both
design: readability, writability, and reliability. In this paper, we use
languages, and provide detailed instructions on getting the Swift
the three R’s to compare the recently-spawned language Swift to
compiler running on Linux.
the classic C++. We assume that the reader is already familiar with
C++, so the bulk of the paper discusses interesting features of Swift
in the context of the isomorphic feature in C++. 2.1 Structure and Syntax
Swift is Apple’s preferred language for developing apps for the A Swift program is organized into classes and methods, as are C++
macOS and iOS platforms. It was the brainchild of Apple employee programs. However, no ”main” method is used: code not wrapped
Chris Lattner (who is also known for overseeing remarkable projects in method or classes is executed in lexical order. Swift also does not
like the LLVM compiler toolchain and Apple’s XCode environment) distinguish, like C++, between header files and source files: there is
[2]. Lattner began work on Swift in 2010, and it was released in no way to declare a method or class without defining it. For large
2014. In just two years, the language rose to #12 on the TIOBE programs, one simply uses multiple files, where dependencies must
index of language popularity [10]. Swift is a compiled, statically- be compiled first. (Like C++, Swift requires methods and classes
typed, multi-paradigm language, fully supporting object-oriented to be defined before one may call or instantiate them: however,
and functional programming [8]. Lattner states that Swift drew unlike C++, it is possible to declare and define extensions to classes
”ideas from Objective-C, Rust, Haskell, Ruby, Python, C#, CLU, and after the class has been defined, so a class might be declared over
far too many others to list” [2]. Unsurprisingly, he does not name multiple files.)
C++ among his inspirations, since many of Swift’s notable design Swift’s syntax largely fits into the C family of languages: one
choices are safeguards against common C++ bugs. The version of uses curly-braces to define blocks, double-slashes for single line
Swift considered in this paper, Swift4, was released in 2017. comments, and slash-star for multi-line comments. Whitespace is
Our comparison language, C++, was created by Danish academic ignored; object members are accessed using the dot (.). There are
Bjarne Stroustrop in 1979 [6]. C++ built on C, adding classes and a few small breaks with tradition: Semi-colons are not required
a powerful STL (Standard Template Library). Also like Swift, C++ to delimit statements on different lines, and parentheses are not
is a compiled, statically-typed, and multi-paradigm language: it required for if, else, and switch conditionals. Swift is free-form and
supports imperative programming, object-oriented programming, case-sensitive [8].
and treats functions as first-class citizens. C++ is maintained by Figure 1 shows a simple program in Swift, and Figure 2 shows
the ISO (International Standardization Organization), and new ver- the same program translated to C++. Both programs have a static,
sions have been released every 3 years since 2011 (we consider the unsorted list of integers, and ask the user for an index, then provide
2011 version here.) C++ is popular for complex, high-performance the kth-largest number in the list. Here are some notes on the
projects. sample program:
We find in this paper that Swift’s design precludes many common On Line 1, we import the Foundation library; it contains many
C++ type and bounds errors, and that Swift has better tools for of Swift’s core features like classes and strings. On line 3, we use
string processing. C++, however, performs significantly faster in readLine() to input a string. Now we want to convert the string to
an integer, but what if the string is null, or the conversion returns
CpS350’17, Greenville, SC, USA
2016. . null? As we’ll see, Swift requires us to explicitly acknowledge the
DOI: possibility of null variables (also called ”optional types”). The ”?”
CpS350’17, Dec 5, Greenville, SC, USA Jacob Brazeal

1 import Foundation 2.2 Language Processor

2 The Swift compiler is available for Linux and MacOS. For the
3 let index : Int ? = Int ( readLine ()!) reader’s convenience, we provide a short guide to running Swift
4 on Ubuntu 16.10; it is a condensed version of the steps are given
5 let randomNumbers = [3 ,5 ,6 ,2 ,4 ,9 ,11 ,1] in [3], in the Linux section: please refer to that reference if any
6 let biggestToSmallest = clarifications are required.
7 randomNumbers . sorted { $1 > $0 }
8 if index < randomNumbers . Length { (1) Open the Terminal (right-click on the desktop and click
9 let nthElement = ”Open Terminal”). Unless otherwise stated, code snippets
10 biggestToSmallest [ index !] provided in this guide should be entered into the Terminal,
11 print ( nthElement ) and run by pressing the Return key.
12 (2) Install required dependencies:
13 } sudo apt-get install clang libicu-dev
(3) Open the browser, and visit the following link to download
the latest binary release:
Figure 1: A sample Swift program.
swift-4.0.2-RELEASE-ubuntu16.10.tar.gz .
1 # include < iostream > (4) Navigate to the Downloads folder by entering the follow-
2 # include < algorithm > ing command: cd /home/USERNAME/Downloads , where
3 # include < vector > USERNAME is your username.
4 # include < functional > (5) Import the PGP keys into your keyring:
5 int main () { wget -q -O - | \
6 int index ; gpg --import -
7 std :: cin >> index ; (6) Extract the archive with the following command:
8 std :: vector < int > randomNumbers =
tar xzf swift-4.0.2-RELEASE-ubuntu16.10.tar.gz
9 {3 ,5 ,6 ,2 ,4 ,9 ,11 ,1};
This creates a usr/ directory in the location of the archive.
10 std :: vector < int > biggestToSmallest =
(7) Add the Swift toolchain to your path as follows:
11 randomNumbers ;
12 std :: sort ( export PATH=/home/USERNAME/Downloads/usr/bin:"${PATH}"
13 biggestToSmallest . begin () , (again, USERNAME is your username.)
14 biggestToSmallest . end () , (8) Now, open the text editor of your choice (for example, you
15 std :: greater < int >() can use the Vi editor by typing vi testprogram.swift )
16 ); (If you would like more information about working with
17 if ( index < randomNumbers . size () ) { the Vi text editor, please visit mat-
18 int nthElement = loff/UnixAndC/Editors/ViIntro.html; any other editor is
19 biggestToSmallest [ index ]; fine, assuming you can save the file in the appropriate
20 std :: cout << nthElement << std :: endl ; directory.)
21 } (9) Enter the Swift program you want to use, and save it to
22 } your home directory as ”testprogram.swift.”
(10) Exit the text editor. Now enter cd ../.. to return to
your home directory.
Figure 2: The sample program in C++. (11) Now you can run the program like this: swift testprogram.swift .

Figure 3 shows the author running a Swift program in his termi-

and ”!” operators help us work with optional types, and we’ll discuss
them in section 3.1. On line 5, we find array literal syntax, which 3 LANGUAGE FEATURES
uses square brackets instead of C++’s curly brackets. On line 6 we In this section, we consider the following areas of contrast between
copy a sorted version of the original list, and use lambda syntax to Swift and C++ in terms of readability, writability, and reliability:
sort it in reverse. Swift provides some nice syntactic sugar to work Types, variables, expressions, control statements, and subroutines.
with lambdas; C++ requires a capture list and explicit parameter We also describe Swift’s generics.
and return types, but Swift can infer these. On line 9, we check to
see if the index is in bounds, and on line 10, we get the element
requested by the user, using the bang (”!”) to convert the type from 3.1 Types
Int-optional to Int (see section on Types). On line 12, we call the Types are the foundational difference between C++ and Swift –
built-in print method. Swift is even more strongly-typed than C++. In Swift, every type
A Comparison of C++ and Swift CpS350’17, Dec 5, Greenville, SC, USA

Figure 3: Running a Swift program.

(like Int, or String, or Character) has both a default and an op- intent when they contain symbols like emoji or diacritics. However,
tional version. Default types can never be nil (Swift’s term for Swift strings are less writable, because this abstract representation
undefined), while optional types can. We immediately see a con- makes it impossible to directly index an array, as one would in
trast with C++: C++ allows reference types to be nil, but not value C++ (see Figure 5 for the cumbersome syntax); the underlying data
types. To declare an optional variable in Swift, one can write: structure is a linked list. It’s still possible to get the raw contents of
let myVar : Int? = 5 , in contrast to declaring the equivalent the strings an array of 8-bit or 16-bit characters, using the properties
default variable, let myVar : Int = 5 . The entire syntactical utf8 and utf16 .
system of Swift is aligned around prodding the code-author toward One other type forming a significant contrast is the pointer. Swift
default types (for example, optional types must be converted to de- has pointers, but they are hidden behind a layer of abstraction not
fault types before they are evaluated), while offering lots of support found in C++. Interestingly, pointers are extremely unwieldy; you
for fallbacks if one tries to use an optional type that is currently must use pointer objects, and specifically state how much memory
nil. Since null-reference errors are some of the most famous and you want to deallocate when freeing pointers. See Figure 4 for
common bugs in C++ programs, this philosophy of Swift marks a example usage of passing a pointer to a function and adjusting
welcome improvement in reliability. Also, since the syntax of the the memory referred to by the pointer: note that memory pointed
language requires one to know at any time whether a variable could to by a pointer object is given by its ”memory” property. While
be nil or not, one can reason more effectively about the behavior of Swift is more reliable than C++ in that it discourages pointers, Swift
the program - an improvement in reliability. pointers are also difficult to read and write. If a program actually
Strings form a rich contrast between Swift and C++. In both required pointers, C++ would be far easier to use.[8]
languages, one can use a native, pared-down string (In Swift, this
is a String, in C++, a char array), or an extended version from
the standard library (Swift’s NSString, C++’s std::string). Swift’s 3.2 Variables
NSString is a reference type, and extends the String, which is a Non-optional types always have a default value (for Ints, this is
value type, by adding a few methods like ”Length.” This contrast 0; for Strings, the empty string; for Bools, false.) Optional types
is less stark than the one in C++: a C string is simply a pointer to have a default value of nil. C++ famously gives global and member
a null-terminated char array, providing no methods, while a C++ variables default values, but does not give defaults to local, prim-
string wraps a pointer to a char array, can be resized, overloads itive types. One must appreciate how Swift heads off undesired
operators and provides many methods. We will focus on Swift’s behavior in this way, showing itself more reliable than C++. Swift
String, since it brings out all the important differences between provides extensive tools to make sure that it is obvious when we are
Swift and C++. Since the String is a value type, it is usually copied manipulating an optionally-typed variable, and to provide a safe
on assignment. (However, as an optimization, Swift won’t copy and explicitly defined way to recover from a nil value (see section
strings when the copy is not modified; it uses a pointer to the 3.3 for some of the operators used).
original string.) The next difference is that a Swift String is more All types are determined at compile time, but the compiler can
abstract than a std::string. Instead of representing a char array, it often determine types itself (from default values, for example) and
represents a collection of Unicode graphemes (code points) that only requires the programmer to annotate ambiguous types. For
may individually take up more than one byte. Thus, Swift strings example, we can write var str = "Hello World!" , and Swift
are more reliable, since they are more likely to reflect a developer’s infers it to be a string. This is one of the few features in Swift that
CpS350’17, Dec 5, Greenville, SC, USA Jacob Brazeal

1 func work ( p : UnsafeMutablePointer < Float >) { 1

2 if p != nil { 2 let primes = [" Summer ", " Fall ",
3 p . memory = 10 3 " Winter ", " Spring "]
4 } 4 for s in seasons [1...] {
5 println ( p ) 5 print (s)
6 println ( p . memory ) 6 }
7 } 7 // prints Fall Winter Spring
9 var f : Float = 0.0
10 var fPointer : UnsafeMutablePointer < Float > = Figure 6: Iterating through an array with ranges.
11 UnsafeMutablePointer . alloc (1)
12 1
13 work (& f ) 2 for x in [2...10] {
14 work ( fPointer ) 3 print (x)
15 fPointer . dealloc (1) 4 }
5 // prints 2 3 4 5 6 7 8 9 10

Figure 4: Swift pointers. [4]

Figure 7: A for loop with ranges.
2 let str = " Merry Christmas "
3 str [ str . startIndex ] only a few lines of code in C++, but we can see that Swift encourages
4 // M reliable behavior by making the correct code more writable.
5 str [ str . index ( Swift also provides the standard comparison operators == and !=,
6 str . startIndex , offsetBy : 6)] which always perform a value comparison, but also the operators
7 // C === and !==, which always performance a reference comparison.
This nicely resolves the issue in C++ that one can’t know just by
looking at the code which kind of comparison is being performed,
Figure 5: Indexing values in a Swift string. improving readability, and also writability, since it is not at all
obvious how to perform, say, a value comparison of classes in
C++. (One would probably do this via operator overloading - time-
introduces unreliable, unreadable behavior compared to C++. C++
consuming and hard to implement correctly.)
requires syntactic recognition of types (e.g.
The last upgrade in operators is the addition of range operators,
std::string str = "Hello World" ), which (at a small cost which are far more writeable than the comparable idioms in C++.
to writability) greatly improves one’s ability to reason about a For example, 2...10 generates the values 2 through 10, which
program. Like C++, Swift’s types are static and cannot change. we can iterate through using a for-loop (see Figure 7). Similarly,
Swift recognizes a stronger divide between numeric types than 2..<10 gives the values 2 through 9. In addition, we can have un-
C++ does. Explicit casting is required to convert a double to an
finished and unstarted ranges like ...2 and 2... , which imply
integer (via truncation), or to convert an integer to a double. One
a lower and upper bound that are as low and as high (respectively)
must write var a : Int = 1 var b : double = Double(a) ,
as possible without causing a runtime error. For example, we can
to avoid a compile-time error. Arguably, this increased rigor im- loop over an array with for-in loop over an unfinished range-index
proves reliability, but like most improvements to reliability is slightly as shown Figure 6. This code prints all the elements of the given
more painful to write. [8] array, starting with the second. [8]
3.3 Expressions 3.4 Control Statements
Swift’s operators, while including the standard arithmetic, logical,
Switch statements in Swift are much easier to write than switch
and bitwise operators in C++, have some important upgrades in
statements in C++, and are also more reliable. C++’s switch state-
reliability. In particular, overflow is impossible. Overflow causes a
ment are error-prone because of the problem of accidental fall-
run time error. On the one hand, this check surely slows execution,
through. However, Swift does not fall through consecutive switch
but it helps pinpoint what is almost always undefined, undesired
statements by default. One must explicitly use the fallthrough key-
behavior in C++. To allow overflow, one must explicitly use the
word to continue checking case statements after a match is found
characters &+ instead of + , &* instead of * , etc. Another (thus, the break keyword is not required, since breaking is the
useful operator is the nil-coalescing operator ( ?? ). ?? takes an default behavior.)
optional type and its equivalent non-optional type, and return value Most importantly, though, Swift’s switch statements are much
of the first variable if it is not nil, otherwise the value of the default more expressive and powerful than C++’s switch statements. C++,
variable: for example, supposing count is an optional Int, we can of course, provides only a glorified jump table, able to match only on
write var a: Int = cnt ?? 0 . The same functionality requires primitive types. What kinds of matching are possible in Swift? First,
A Comparison of C++ and Swift CpS350’17, Dec 5, Greenville, SC, USA

1 1
2 let somePoint = (1 , 1) 2 func sample ( Int : inout number ,
3 switch somePoint { 3 name : String ) -> Int {
4 case (0 , 0): 4 print ( number )
5 print ("\( somePoint ) is at the origin ") 5 print ( name )
6 case (_ , 0): 6 name = name - 1
7 print ("\( somePoint ) is on the x - axis ") 7 return name + " :) "
8 case (0 , _ ): 8 }
9 print ("\( somePoint ) is on the y - axis ") 9
10 case ( -2...2 , -2...2): 10 # call :
11 print ("\( somePoint ) is inside the box ") 11 let num : Int = 4
12 default : 12 sample ( number : num , name : " Joe " )
13 print ("\( somePoint ) is outside of the box ")
14 } 14 print ( num )
15 # 3

Figure 8: Switch statement with tuples in Swift. [8]

Figure 10: Paramter passing in Swift.
2 let a : Int ? = 1; reliability. In the following discussion, it may be helpful to refer to
3 Figure 10.
4 guard let b = a! else { By default, all parameters passed to methods are constants and
5 print ( b ) cannot be modified (as if, in C++, the ”const” keyword was used
6 } in the function declaration for each variable). However, we can
explicitly specify ”in-out” parameter passing so that the variables
used to call the parameter are updated to the parameter’s new
Figure 9: A Guard statement in Swift.
values on function return (in Figure 10, this is parameter number .
In-out parameters do not exist in C++: for a rough equivalent,
one would use reference types that are simply pointers to the vari-
we can match Int variables to ranges: case 2...10 matches all
able passed. C++’s version is more writeable, since it’s more conve-
integers from 2 to 10. Also, we can also perform pattern matching
nient to be able to modify variables by default, but in-out parameter
on tuples, as shown in Figure 8. Notice that we can place variables
passing does eliminate potentially unexpected behavior when the
in the tuples, so that the variable parts can have match any value
same variable is passed by reference to two parameters in a func-
in the switch variable. It’s also possible to use the values of these
tion. In addition, encouraging constant variables can improve one’s
variables in the code handling each case. Not only this, but we
ability to reason about a program. Thus, Swift’s approach is more
can add logical checks into the cases with the where clause. For
reliable than that of C++.
example, the case case (a,b) where sqrt(a*a + b*b) < 1: Swift’s functions come with some additional boiler plate that
matches tuples that are within a unit of the origin. makes function calls easier to read than methods in C++ (and with
Another interesting Swift control statement is the Guard state- a good IDE, they are no harder to write). Specifically, all Swift
ment, which helps the language’s reliability by encouraging devel- parameters must be named in the function call (again, see Fig.
opers to think of handling null variables as a natural, syntax-level ]reffig:funsamp) unless the name is prefixed with an underscore
task. The Guard statement is a specialized If statement used to ( _ ) in the function header.
check for null variables. As one can see in Figure 9, the condition of To make up for the pain of parameter-passing, Swift has another
the Guard clause checks to see if the assignment can be performed feature that is easier to write than its counterpart in C++: the
(that is, that none of the variables being unwrapped are nil). If the closure (C++’s lambda). Lambdas are famous for their burdensome
statement cannot be performed, the else clause is triggered. One syntax and type issues (lambda types are actually compiler-defined
could use this method to return early from a function or constructor, in C++), while closures are very simple to write. For example,
for instance, based on how much information was passed to the suppose one is engaging in functional programming and calling a
function. The C++ equivalent would be to either explicitly check function that take a closure as its parameter. In this case, the body
for null variables or to use a try-catch block, but the guard clause of the closure can be left outside the calling parentheses, and the
is cleaner than either option. [8] (See Figure 9.) Swift compiler can infer the types of the parameters and return
value. Indeed, it is not even necessary to name the parameters! We
3.5 Subroutines recall a line from the sample program:
Writing methods in Swift is a somewhat more involved process let arr = randNumbers.sorted{$1 > $0}
than writing methods in C++: in particular, parameters are harder In this expression, {$1 > $0} is a complete closure, where
to write correctly, but they are easier to read, and have improved the compiler infers a return type of ”Boolean” and passes the first
CpS350’17, Dec 5, Greenville, SC, USA Jacob Brazeal

1 1
2 func someFunction <T: SomeClass , 2 func someFunction <T: Equatable >
3 U : SomeProtocol >( someT : T , someU : U) { 3 (a : T , b : T) -> Boolean {
4 } 4 return a == b
5 }

Figure 11: A polymorphic method in Swift. [8]

Figure 12: An equatable template in Swift.

2 func someFunction <T : SomeProtocol , S >
and second parameters automatically to the numbered tokens. The 3 (a : T , b : S)
equivalent lambda in C++ is less compelling, and is found in Fig. 2. 4 where S: Equatable ,
We should also note here that scoping works nearly identically 5 S == T. Child {
in the two languages: Swift, like C++, has global variables and 6 }
block-level scoping, and variables are collected by the garbage col-
lector once they pass out of scope and no other references to them
exist; Swift follows Apple tradition in using reference counting for Figure 13: A where-clause template in Swift.
garbage collection. Notably, this means of collection can prevent
a class of reliability problems with C++ programs, the infamous
”double free.” Notably, as long as one avoids pointers (which are not 4 CONCLUSION
always subject to garbage collection), one should never encounter a On the whole, Swift is more reliable and readable than C++. Many
double-free error in Swift, while the same precaution is insufficient of the most common bugs in C++ programs are difficult to write
when working with C++. [8] in Swift (integer overflow and null references, for example.) Mean-
while, Swift’s advanced switch structures, closures, and ranges are
3.6 Generic Programming more readable than C++’s equivalent (when it exists). Swift is not
always more writable: sometimes because the language requires the
Swift’s generic types are very flexible. To begin, consider the poly- user to write logically complete code, and sometimes to discourage
morphic function shown in Figure 11. We see that we can provide poor practices.
templated class types (the semantics of which are similar to tem- Swift’s main advantage for its user base, though, is that it is a
plated class types in C++: type T must inherit from SomeClass). language designed by Apple for iOS and macOS development. Few
However, types can also implement protocols. languages have well-suited APIs and frameworks for this task, and
What are protocols? Protocols are a way to create more versatile among this group Swift quickly emerged as a leader [9]. It grew from
templates for classes in generic data structures. They are used a new release in 2014 to the the #12 language used by professional
much like the Interface pattern is used in .NET languages. That developers in Stack Overflow’s 2017 developer survey [5]. Swift’s
is, an interface is defined like a class, and whatever methods and main weakness is that it is not used for Android development, so
members it defines must also be implemented by the polymorphic cross-platform languages can be more efficient for developers [1],
class. Notably, in the sample shown, it is not necessary for the class and its star has fallen slightly, according to the TIOBE index, where
U to specifically inherit from the protocol, although it may: it must Swift fell from #10 and #20 in the last year [10].
only include the methods and members defined by the protocol. Ultimately, Swift’s expressiveness and reliability are luxuries
Swift also allows us to require certain properties of types (see that come at the cost of performance, and not everyone can afford
Figure 12). The Equatable restriction requires the object to support to pay that price. However, if Swift can become fully cross-platform,
the ”==” and ”!=” operators; this can be helpful, for instance, when it seems likely that its adoption will only increase.
writing a generic library. In Figure 12, we can pass Ints or Floats
to someFunction, but not user-defined classes without the ’==’ REFERENCES
operator). [1] 2017. Apple’s Swift is Losing Developers to Multiplatform Frameworks.
To make more complex restrictions on types, we can use a (2017).
where clause in our template. (See Figure 13.) In this code, we apples-swift-is-losing-developers-to-multiplatform-frameworks.html
[2] 2017. Chris Lattner’s Homepage. (2017).
require S to be an equatable class, T to implement the protocol [3] 2017. Download Swift. (2017).
SomeProtocol , and for S to be the same type as T’s child Child . [4] 2017. How to set & get value of pointer Swift. (2017).
[8] [5] 2017. Stack Overflow Developer Survey 2017. (2017). https://insights.
One of the main benefits of having such a flexible and expressive
templating language is that we can find out much more easily why [6] 2017. Stroustrop: Biographical Information. (2017).
certain code does not compile: we can see immediately which [7] 2017. Swift, C++ Performance. (2017).
where clause, for instance, is triggering an inconsistency. C++’s 12/swift-performance/
[8] 2017. The Swift Programming Language Reference. (2017). https:
templating language is also powerful, but produces notoriously //
vague error messages. Swift Programming Language/
A Comparison of C++ and Swift CpS350’17, Dec 5, Greenville, SC, USA

[9] 2017. Swift vs. Objective C. (2017).

[10] 2017. TIOBE. (2017).