Home Icon Home Resource Centre 2D Vector In C++ | Declare, Initialize & Operations (+ Examples)

2D Vector In C++ | Declare, Initialize & Operations (+ Examples)

A 2D vector in C++ represents dynamic arrays that facilitate the manipulation of data in code. There are multiple ways to declare and initialize arrays adding flexibility to the process of writing code.
Shivani Goyal
Schedule Icon 0 min read
2D Vector In C++ | Declare, Initialize & Operations (+ Examples)
Schedule Icon 0 min read

Table of content: 

  • What Are 2D Vectors In C++?
  • How To Declare 2D Vector In C++?
  • How To Initialize 2D Vector In C++?
  • C++ Program Examples For 2D Vectors 
  • How To Access & Modify 2D Vector Elements In C++?
  • Methods To Traverse, Manipulate & Print 2D Vectors In C++
  • Adding Elements To 2-D Vector Using push_back() Function
  • Removing Elements From Vector In C++ Using pop_back() Function
  • Creating 2D Vector In C++ With User Input For Size Of Column & Row
  • Advantages of 2D Vectors Over Traditional Arrays
  • Conclusion
  • Frequently Asked Questions
expand icon

C++ is a powerful and versatile dynamic programming language with extensive support for data structures and a sequence of containers. Among these, 2D vectors, also known as dynamic arrays, offer a flexible way to represent and manipulate two-dimensional vector arrays in C++ language. In this article, we will explore the concept of 2D vectors in C++, their usage, declaration and initialization, basic operations on vectors, various examples, and their advantages over traditional arrays. So let's get started!

What Are 2D Vectors In C++?

2D Vector In C++ Definition

A 2D vector is essentially a vector of vectors, where each vector represents a row of elements. Through the vector appearance, we can understand that it is similar to matrices. Each element of the vector represents a row, and each row is a vector in itself that holds the individual elements of the row.

  • They have dynamic properties, i.e., they can grow or shrink in size depending on the need of the application, making them highly memory efficient, unlike arrays which are fixed in size.
  • We must include the standard template library and the <vector> header file to use 2D vectors in C++.

They are widely used in applications that involve grid-based data structures and algorithms. Applications in fields like image processing, game development, computer graphics, simulations, and scientific computing all involve the use of 2D vectors.

Two-Dimensional Vector's syntax:

// Using arrays
double vector[2] = {x, y};

// Using std::vector
#include <vector>
std::vector<double> vector = {x, y};

2D Vector In C++ | Declare, Initialize & Operations (+ Examples)

How To Declare 2D Vector In C++?

As we've mentioned, we need to include a header file before we start writing code involving vectors or 2D vectors in C++. The vector header file is part of the standard library and provides the necessary functionality to work with vectors.

Declaration of 2D vector in C++ mechanism

It contains the implementation of the vector class template, which allows us to create, manipulate and manage 2D vectors in C++. There are various methods, such as using initializer lists, fill constructors, and using push_back() to initialize 2D vectors in C++.

Code Example:

Code explanation:

  1. We are declaring a vector called vector v2.
  2. There are no values assigned to it, and it is not initialized.
  3. Since there are no elements to display, there will be no output produced by this code. This is just the basic declaration of a 2D vector.

Time Complexity: O(1)
Space Complexity: O(1)

How To Initialize 2D Vector In C++?

We have already seen how to declare a 2-dimensional vector. What comes next? You guessed it right; we are talking about initializing C++ 2D vectors. There are several methods to initialize a 2D vector in C++. Here are some common approaches:

2D Vector Initialization In C++ Using Fill Constructor

In C++, you can initialize a 2D vector using the std::vector fill constructor. This constructor allows you to create a 2D vector with a specific number of rows and columns, and all elements will be initialized to the given value. Here's how you can do it:

Code: To Initialize a 2D vector of n rows and m columns with a value of 0.

Output: 

0 0 0 0
0 0 0 0
0 0 0 0

Explanation: 

In this example, the std::vector fill constructor is used to create a 2D vector named twoDVector.

  1. We begin by declaring three integer variables, rows, columns, and intialValue, and initialize them with the values of 3, 4, and 0, respectively.
  2. These variables are then used to initialize a vector with the std::vector fill constructor, as mentioned in the comments.
  3. The vector has 3 rows and 4 columns, and all elements are initialized to the initialValue (which is set to 0 in this case).

This method is particularly useful when you want to initialize a 2D vector with the same value for all elements.

2D Vector Initialization In C++ Using resize() Function

In C++, you can initialize a 2D vector using the resize() function from the std::vector class. The resize() function allows you to specify the size of the 2D vector, and if needed, it also initializes the elements to a default value (0 for integers, 0.0 for doubles, etc.). The example given below shows how this can be done.

Code Example: 

Output: 

0 0 0 0
0 0 0 0
0 0 0 0

Explanation: 

In this example, the 2D vector twoDVector is initialized to have 3 rows by calling twoDVector.resize(rows);.

  1. We begin by including the iostream and vector header files.
  2. Then we declare and initialize three integer variables, rows, columns, and intialValue, with the values of 3, 4, and 0, respectively.
  3. The std::vector is then used to create a 2D vector named twoDVector with 3 rows and four columns, where each element is 0 (initialValue).
  4. Next, we call the resize() function to set the number of columns for that row and initialize all elements to the initialValue (which is set to 0 in this case).
  5. We then use nested for loops and the cout statement to input the value of each element of the vector and print it, respectively. 

2D Vector Initialization In C++ Using push_back() Function

To initialize a 2D vector in C++ using the push_back() function, you can start with an empty 2D vector and dynamically add rows (vectors) to it using push_back(). Then, you can use push_back() again to add elements to each row. Look at the example below to see how it can be done.

Code Example: 

Output: 

1 2 3
4 5 6
7 8 9

Explanation: 

  1. In this example, we first declare an empty 2D vector called twoDVector.
  2. We then add three rows to the 2D vector using the push_back() function thrice.
  3. Each row is represented by a vector of integers, i.e., {1, 2, 3}, {4, 5, 6}, and {7, 8, 9}, respectively. 
  4. The nested for loop then works to input the value of vector elements.
  5. The output is printed using the cout statement. It shows the 2D vector initialized with 3 rows and 3 columns, with custom values in each element as specified.

Note: Using push_back() is particularly useful when the size of the 2D vector is not known beforehand and needs to be populated dynamically.

2D Vector Initialization In C++ Using Initializer Lists

Initializer lists are convenient syntaxes for initializing objects, including vectors, with a list of values. It allows us to provide initial values directly when creating the object. It is a common way of initializing elements of 2D vectors and is widely used. 

Code Example: 

Output: 

1 2 3
4 5 6
7 8 9

Explanation: 

In this example, 

  1. We declare and initialize a vector called twoDVector directly using an initializer list.
  2. The curly braces indicate the rows of the 2D vector, and the nested curly braces represent the elements within each row.
  3. The output shows the 2D vector initialized with 3 rows and 3 columns, with custom values in each element as specified in the initializer list.

Using initializer lists is a convenient and concise way to initialize 2D vectors when you know the values you want to assign beforehand. It provides a cleaner syntax compared to other methods, like using nested loops or push_back().

2D Vector In C++ | Declare, Initialize & Operations (+ Examples)

C++ Program Examples For 2D Vectors 

Example 1: Creating a 2-Dimensional vector of equal number of columns.

Output: 

1 1 1
1 1 1
1 1 1
1 1 1

Explanation: 

In the code above, 

  1. We create a 2D vector named twoDVector with 4 rows and 3 columns, where all elements are initialized to 1.
  2. We use nested loops to loop through the 2D vector and output its elements row by row.
  3. The output will be a 4x3 grid with all elements set to 0.

Example 2: To define the 2D vector with different sizes of columns.

Output: 

1 2 3
4 5
6 7 8 9
10

Explanation: 

In the example above,

  1. We create a 2D vector named twoDVector using the std::vector container.
  2. Each row of the 2D vector is represented by a separate inner vector.
  3. The twoDVector is initialized with four rows of different sizes: Row 0: {1, 2, 3} (3 columns) Row 1: {4, 5} (2 columns) Row 2: {6, 7, 8, 9} (4 columns) Row 3: {10} (1 column)
  4. The program then outputs the contents of the 2D vector.
  5. Each row is printed on a separate line, and the elements within each row are separated by spaces.
  6. The output shows the 2D vector with different sizes of columns for each row, as specified during initialization.

Example 3: To define the 2D vector of n rows and m columns with input values

Output: 

Enter the number of rows: 3
Enter the number of columns: 2
Enter 6 integer values:
3 5 6 0 8 6
The 2D vector you entered:
3 5
6 0
8 6

Explanation: 

In this code:

  1. We begin by declaring two integer variables n and m, in the main function.
  2. Then using std::cout, we print strings 'Enter the number of rows' and 'Enter the number of columns', thus prompting the user to input the number of rows and columns.
  3. The inputs are read using the std::cin.
  4. Next, we create a 2D vector twoDVector with n rows and m columns using std::vector.
  5. We then use nested loops to input values for each element of the 2D vector.
  6. The program then outputs the contents of the 2D vector to display the values entered by the user.
  7. When you run this program, it will prompt you to enter the number of rows and columns, followed by "n * m" integer values.
  8. After entering the values, the program will display the 2D vector with the entered values.

Check this out- Boosting Career Opportunities For Engineers Through E-School Competitions

How To Access & Modify 2D Vector Elements In C++?

Accessing and modifying elements in 2D vectors in C++ can be performed using different methods. We will discuss two of the most popular methods, i.e., using double square brackets and the at() function, in this section.  

Using Double Square Brackets([ ] [ ])

2D vectors can be accessed in the same way as accessing and modifying 2D arrays in C++ by using the double square brackets and specifying the indexes pertaining to the row and column of the element we want to access. However, this method does not provide bound checking, and hence 'out of range' exceptions will not be thrown if we access indexes that are not in the vector.

Code Example:

Output:

printing the 2D vector:
1 2 3
4 5 6
7 8 9

printing the 2d vector after modifying the elements:
1 2 3
4 5 0
7 0 9

Code explanation:

  1. The code declares and initializes a 2D vector using an initializer list. It then prints the original vector using nested for loops.
  2. It then modifies specific elements of the vector by accessing their indexes using double square brackets(“[][]”), and we assign new values to those indexes.
  3. We then print the modified vector using nested for loops.

Time Complexity: O(m*n), where m is the no.of.rows and n is the no.of.columns
Space Complexity: O(m*n) where m*n is the no.of elements in the 2D vector.

Using The at() Function

The at() function is another method that is used to access and modify elements of 2D vectors in C++. It has a very useful advantage in that it provides bounds checking, and hence an 'out of range' exception will be thrown, which helps us in debugging and maintaining the code. The indexes are specified pertaining to the row and column of the element in the 2D vector.

Code Example:

Output:

printing the 2D vector:
1 2 3
4 5 6
7 8 9

printing the 2d vector after modifying the elements:
1 2 3
4 5 0
7 0 9

Code explanation:

  1. The code declares and initializes a 2D vector using an initializer list.
  2. It then prints the original vector using nested for loops and cout statements.
  3. It then modifies a specific single element of the vector by accessing their indexes using the at() function, and we assign new values to those indexes.
  4. We then print the modified vector using nested for loops.

Time Complexity: O(m*n), where m is the no.of.rows and n is the no.of.columns
Space Complexity: O(m*n) where m*n is the no.of elements in the 2D vector.

Methods To Traverse, Manipulate & Print 2D Vectors In C++

In C++, there are several methods to traverse (iterate through), manipulate and print the elements of a 2D vector (vector of vectors). Here are some common methods:

Range-Based For Loops To Traverse C++ 2D Vector

A very easy and efficient way to traverse 2D vectors in C++ is by using a range-based standard for loop. They provide an effective and convenient way to iterate over a 2D vector without having to use iterators explicitly. Given below is a code sample to help you better understand how range based for loops are used

Code Example:

Output:

1 2 3
4 5 6
7 8 9

Code explanation:

  1. The given code declares and initializes a 2D vector using an initializer list.
  2. The vector contains 3 inner vectors, which represent the ropes of the 2D vector.
  3. It then uses a range-based for loop to traverse the vector and print its integer variables.

Time Complexity: O(m*n), where m is the no.of.rows and n is the no.of.columns
Space Complexity: O(m*n) where m*n is the no.of elements in the 2D vector.

Traversing 2-D Vectors In C++ Using Iterators

Iterators are objects that allow traversal and access to the elements of 2D vectors in C++. They provide a flexible and powerful way for sequential iteration over the elements of the 2D vector, helping in facilitating operations such as accessing, modifying, and erasing elements. Row iterators are used to iterate through rows, while column iterators are used to iterate through columns of a 2D vector.

Code Example:

Output:

printing the 2D vector:
1 2 3
4 5 6
7 8 9

printing the 2d vector after modifying the elements:
2 4 6
8 10 12
14 16 18

Code explanation:

  1. The code initializes a 2D vector with values using an initializer list and prints the vector using iterators.
  2. It uses nested for loops along with iterator values to traverse the vector.
  3. It then modifies each element of the vector by multiplying it by 2 and prints the modified vectors using a combination of iterators and nested for loops.

Time Complexity: O(m*n), where m is the no.of.rows and n is the no.of.columns
Space Complexity: O(m*n) where m*n is the no.of elements in the 2D vector.

Utilize Indexing To Iterate Over A Vector In C++

Using indexing to iterate over a vector is a straightforward approach and allows you to access and process individual elements of the vector easily. We can utilize indexing to iterate over a vector in C++ using a simple for loop. Here's an example:

Code: 

Output: 

Using indexing to iterate over the vector:
10 20 30 40 50

Explanation: 

  1. In this example, we have a vector called myVector with elements {10, 20, 30, 40, 50}.
  2. We use indexing with a for loop counter i to access each element of the vector.
  3. The loop runs from i = 0 to i = myVector.size() - 1, where myVector.size() gives the number of elements in the vector.
  4. In each iteration of the loop, we use myVector[i] to access and print the element at the index i.

Printing A 2D Vector Using Nested Loops

To print a 2D vector using nested loops in C++, you can use two nested for loops—one for iterating through the rows and another for iterating through the elements within each row. Here's an example:

Code: 

Output: 

Using nested loops to print the 2D vector:
1 2 3
4 5 6
7 8 9

Explanation: 

  1. In this example, we first create a 2D vector called twoDVector directly with initializer lists.
  2. We then use two nested for loops to iterate through the rows and elements within each row.
  3. The outer loop (i) iterates through the rows using twoDVector.size(), and the inner loop (j) iterates through the elements of each row using twoDVector[i].size().
  4. Inside the inner loop, we access each element of the 2D vector using the indexing twoDVector[i][j] and print it using std::cout.
  5. After printing all elements of one row, we move to the next line using std::cout << std::endl; to display the rows one by one.
  6. This method is straightforward and allows you to access and print individual elements of the 2D vector efficiently.

Adding Elements To 2-D Vector Using push_back() Function

2D vector in C++ | How to add elements using the push_back() function

The push_back() function in C++ is used to add elements to the end of a vector. In the case of a 2D vector, it is used to add new rows to the vector. Each row can have a different number of elements, allowing for a dynamic structure. It’s a powerful tool which is the main advantage when it comes to a vector’s dynamic nature.

Code Example:

Output:

1 2 3
4 5
7 8 9

Code explanation:

  1. The code initializes an empty 2D vector and then adds multiple rows to it using the push_back() function.
  2. Each row is a vector.
  3. The nested for loops then iterate over the vector and prints its elements using the at() function to access individual elements.

Time Complexity: O(m*n), where m is the no.of.rows and n is the no.of.columns
Space Complexity: O(m*n) where m*n is the no.of elements in the 2D vector.

Removing Elements From Vector In C++ Using pop_back() Function

The pop_back() function in C++ is used to pop or remove elements from a vector. The value is removed from the end of the vector. In the case of 2D vectors, the pop_back() function removes the last row of the 2D vector, thus decreasing the number of rows by 1.

2D vector in C++ | Working of pop_back() function

Given below is an example to help you better understand how the pop_back() function works.

Code Example:

Output:

before pop_back():
1 2 3
4 5
7 8 9

after pop_back():
1 2 3
4 5

Code explanation:

  1. The code declares an empty 2D vector and adds multiple rows to it by using the push_back() function.
  2. It then prints the vector by using nested for loops and cout statements.
  3. It then calls the pop_back() function to remove the last row of the vector.
  4. The program again uses the cout statement to print the modified vector using a nested for loop.

Time Complexity: O(m*n), where m is the no.of.rows and n is the no.of.columns
Space Complexity: O(m*n) where m*n is the no.of elements in the 2D vector.

Creating 2D Vector In C++ With User Input For Size Of Column & Row

We can create 2D vectors in C++, where we can input the number of rows and columns and the element values to be stored in the 2D vector from user input. We make use of the fill constructor to create our custom 2D vector, where the number of rows, number of columns, and the elements can be received as input from the keyboard by the user.

Given below is an example to show how to create a 2d vector with user-defined size and input values.

Output:

enter no.of.rows: 3
enter no.of.cols: 4
enter the elements to be stored in 2D vector:
1 2 3 4
5 6 7 8
9 10 11 12

Printing the 2-D vector:
1 2 3 4
5 6 7 8
9 10 11 12

Code explanation:

  1. The code prompts the user to enter the number of rows and columns for a 2D vector using the cout command and scans the input with cin.
  2. It then declares and initializes the vector with the specified vector dimensions.
  3. Once again, it prompts the user to input the elements to be stored in it through nested for loops and the cin stream.
  4. Finally, it uses nested for loops and cout to print the elements of the vector.

Time Complexity: O(m*n), where m is the no.of.rows and n is the no.of.columns
Space Complexity: O(m*n) where m*n is the no.of elements in the 2D vector.

Note: This code can be used as an example for various 2D vector examples as they can be achieved by changing the input based on the requirement. For example, by giving the same input for the number of rows and columns, we get a 2D vector with an equal number of rows and columns. If each element we store in the vector is zero, then we get a 2D vector with all values set to 0. So experiment with input to generate various examples of 2D vectors.

Advantages of 2D Vectors Over Traditional Arrays

2D vectors in C++ offer several advantages over traditional arrays when it comes to representing and manipulating two-dimensional data. Let's explore some of the key advantages:

  1. Dynamic Size: One of the significant advantages of 2D vectors is that they allow dynamic sizing. Unlike traditional arrays, which require a fixed container size specified at compile time, 2D vectors can be resized at runtime using functions like resize() or push_back(). This flexibility enables you to adapt the size of the 2D vector based on the actual data requirements, making it more convenient for real-world applications where data size may vary.

  2. Memory Management: 2D vectors handle memory allocation and deallocation automatically. In other words, they manage memory dynamically, meaning that memory is allocated when elements are added to the vector. And it is deallocated when elements are removed or when the vector items are destroyed. This eliminates the need for manual memory management, which is often error-prone and can lead to memory leaks or buffer overflows in traditional arrays.

  3. Ease of Initialization: Initializing a 2D vector is more straightforward and flexible compared to traditional arrays. You can initialize a 2D vector using the fill constructor, resize function, push_back method, or even with initializer lists, allowing for concise and readable code. In contrast, initializing traditional arrays typically involves nested loops or cumbersome syntax.

  4. Dynamic Row Sizes: 2D vectors can have rows of different sizes ( such as single-row vectors or multiple-row vectors), allowing the representation of irregular or jagged matrices. Traditional arrays require all rows to have the same size, which may lead to wasted memory if the data is irregularly structured.

  5. Range-based For Loop: With 2D vectors, you can use a range-based for loop to iterate through different types of vector elements more conveniently. This syntax simplifies the vector code and avoids potential off-by-one errors that can occur when using traditional loops with array indices.

  6. Standard Library Functions: 2D vectors are part of the C++ Standard Template Libraries (std::vector), which means they come with numerous kinds of useful member functions and algorithms like size(), empty(), begin(), end(), and insert(). These functions make working with different forms of vectors more efficient and expressive.

  7. Copy and Assignment: Copying or assigning 2D vectors is straightforward and safe. You can use the default copy constructor and assignment operator without worrying about deep copying or memory issues. Traditional arrays do not have a built-in copy or assignment functionality, and their manual copying can lead to bugs if not done correctly.

  8. Passing as Function Arguments: 2D vectors can be easily passed as function or positional arguments and returned from functions. They maintain their size and data, making it easier to work with functions that operate on multi-dimensional data.

Conclusion

In the above article, we have discussed, in detail, the concept of  2D vectors in C++ and some of its dynamic features, and the theory behind vector implementation. We now know that-

  • 2D vectors are a powerful data structure in C++, providing a dynamic and efficient way to work with two-dimensional arrays.
  • Their flexibility, ease of use, and built-in memory management make them a preferred choice for various applications.
  • Understanding how to create, initialize, and traverse 2D vectors is essential for handling multi-dimensional data in C++ programs effectively.
  • By mastering 2D vectors, you open up a world of possibilities in handling complex data structures and algorithms. 

Also read- 51 C++ Interview Questions For Freshers & Experienced (With Answers)

Frequently Asked Questions

Q. Are there 2D vectors in C++?

Yes, just like a one-dimensional vector(1D vector), also known as a single-dimensional vector, there are two-dimensional vectors present in C++. A 2D vector is essentially a vector of vectors. Each element of the vector represents a row, and each row is a vector in itself that holds the individual elements of the row.

The basic syntax of 2D Vector: 

#include <vector>
std::vector<std::vector<DataType>> twoDVector;

Also read- Data Types In C++ | A Detailed Explanation With Examples

Q. What is a 2D vector called?

A 2D vector is essentially a vector with vectors. Each element of the vector represents a row, and each row is a vector in itself that holds the individual elements of the row. They are also commonly referred to as grids or matrices.

Q. How to initialize 2D vectors in C++ with value?

Initializer lists are convenient syntaxes for initializing objects, including vectors, with a list of values. It allows us to provide initial values directly when creating the vector object. It is a common way of initializing elements of two-dimensional vectors and is widely used.

Q. What is a fill constructor?

The fill constructor is a constructor that is available for vectors. It is used to initialize the vector with a specified number of elements, all set to the same given value. It allows for quick creation with a specified vector size and initializes all the items in vector to a specified value.

Q. How is push_back() used for 2D vectors in C++?

The push_back() function in C++ is used to add elements to the end of a vector. In the case of a two-dimensional vector, it adds a new row to the vector. Each row can have a different number of elements, allowing for a dynamic structure.

Q. How is pop_back() used for 2D vectors in C++?

The pop_back() function in C++ is used to pop or remove elements from a vector from the back of the vector. The value is removed from the end of the vector. In the case of 2D vectors, the pop_back() function removes the last row of the two-dimensional vector, thus decreasing the number of rows by 1.

Q. What is the resize() function for 2D vectors in C++?

The resize() function in C++ is another powerful method that makes normal vectors dynamic in nature and adds to the flexible nature of vectors. It allows us to add and remove rows or elements within the rows.

Q. How to create 2D vectors in C++ with user input?

We can create 2D vectors in C++, where we can input the number of rows and columns and the elements to be stored in the two-dimensional vector from user input. We can make use of the fill constructor to create our custom normal vector where the number of rows, number of columns, and the vector elements can be received as input from the keyboard by the user.

Q. Can 2D vectors in C++ be accessed in the same way as 2D arrays?

2D vectors can be accessed in the same way as accessing and modifying 2D arrays in C++ by using the double square brackets and specifying the indexes pertaining to the row and column of the element we want to access.

Q. What is the advantage of at() function over indexing([][])?

The at() function is another method that is used to access and modify vector elements of 2D vectors in C++. It has a very useful advantage in that it provides bounds checking. This way, an 'out of range' exception will be thrown, which helps us in debugging and maintaining the code. The indexes are specified pertaining to the row and column of the element in the 2D vector in C++. 

You might also be interested in reading the following:

  1. Storage Classes In C++ & Its Types Explained (With Examples)
  2. Pointers in C++ | A Roadmap To All Types Of Pointers With Examples
  3. Typedef In C++ | Syntax, Application & How To Use It (With Examples)
  4. Guide To Switch Case In C++ & Important Keywords (With Examples)
  5. C++ If-Else & Other Decision-Making Statements (+Examples)
Edited by
Shivani Goyal
Manager, Content

An economics graduate with a passion for storytelling, I thrive on crafting content that blends creativity with technical insight. At Unstop, I create in-depth, SEO-driven content that simplifies complex tech topics and covers a wide array of subjects, all designed to inform, engage, and inspire our readers. My goal is to empower others to truly #BeUnstoppable through content that resonates. When I’m not writing, you’ll find me immersed in art, food, or lost in a good book—constantly drawing inspiration from the world around me.

Comments

Add comment
No comments Image No comments added Add comment
Powered By Unstop Logo
Best Viewed in Chrome, Opera, Mozilla, EDGE & Safari. Copyright © 2024 FLIVE Consulting Pvt Ltd - All rights reserved.