admin管理员组

文章数量:1026156

Mac M1. I learn C++ by Bjarne Stroustrup's book. He show the similar example in his "Programming. Principles and Practice Using C++" book (chapter 5.6.2). Also he writes this exception (out_of_range) is to be occurred.

clang++ --version
Apple clang version 16.0.0 (clang-1600.0.26.4)
Target: arm64-apple-darwin24.0.0
Thread model: posix

My code:

#include <iostream>
#include <vector>

int main(){
    try{
        std::vector<int> items;

        constexpr int size = 5;

        for(int i = 0; i < size; ++i){
            items.push_back(i * 10);
        }

        for(int i = 0; i <= items.size(); ++i){ // out of range!
            std::cout << i << " -> " << items[i] << std::endl;
        }
        std::cout << "Success!" << std::endl;
    }
    catch (std::out_of_range){
        std::cerr << "Range error!" << std::endl;
    }
    catch(...){
        std::cerr << "Something wrong..." << std::endl;
    }
}

Compilation command:

clang++ -std=c++20 main.cpp

Result:

./a.out 
0 -> 0
1 -> 10
2 -> 20
3 -> 30
4 -> 40
5 -> 0
Success!

I've expected to get the out of range exception but it wasn't happened. Why?

Mac M1. I learn C++ by Bjarne Stroustrup's book. He show the similar example in his "Programming. Principles and Practice Using C++" book (chapter 5.6.2). Also he writes this exception (out_of_range) is to be occurred.

clang++ --version
Apple clang version 16.0.0 (clang-1600.0.26.4)
Target: arm64-apple-darwin24.0.0
Thread model: posix

My code:

#include <iostream>
#include <vector>

int main(){
    try{
        std::vector<int> items;

        constexpr int size = 5;

        for(int i = 0; i < size; ++i){
            items.push_back(i * 10);
        }

        for(int i = 0; i <= items.size(); ++i){ // out of range!
            std::cout << i << " -> " << items[i] << std::endl;
        }
        std::cout << "Success!" << std::endl;
    }
    catch (std::out_of_range){
        std::cerr << "Range error!" << std::endl;
    }
    catch(...){
        std::cerr << "Something wrong..." << std::endl;
    }
}

Compilation command:

clang++ -std=c++20 main.cpp

Result:

./a.out 
0 -> 0
1 -> 10
2 -> 20
3 -> 30
4 -> 40
5 -> 0
Success!

I've expected to get the out of range exception but it wasn't happened. Why?

Share Improve this question edited Nov 17, 2024 at 12:40 Andrey Bushman asked Nov 17, 2024 at 12:05 Andrey BushmanAndrey Bushman 12.5k23 gold badges103 silver badges210 bronze badges 8
  • @AhmedAEK learn.microsoft/en-us/cpp/standard-library/… – Andrey Bushman Commented Nov 17, 2024 at 12:12
  • If you read the out_of_range docs it is thrown by the .at member functions, not the brackets operators, those are not checked, in general you shouldn't expect c++ to put unnecessary checks on the hot paths – Ahmed AEK Commented Nov 17, 2024 at 12:15
  • 3 @AndreyBushman If it says what you say it does then it is simply wrong. vector::at throws std::out_of_range not vector::operator[]. – john Commented Nov 17, 2024 at 12:19
  • 1 Use vector's .at() method – Pepijn Kramer Commented Nov 17, 2024 at 12:29
  • 1 You are right the book does say that, it is likely a mistake as bjarne didn't create vector (he didn't even create the STL library which the modern standard library is based on), in any case there are proposals to have C++ do bound checks in the future, but it won't throw an exception and only "error out" in debug mode ..... which a lot of implementations already do anyway. – Ahmed AEK Commented Nov 17, 2024 at 12:32
 |  Show 3 more comments

2 Answers 2

Reset to default 5

I believe you are confusing Bjarne Stroustrup's vector and std::vector.

Stroustrup's PPPheaders.h uses a #define vector Checked_vector. A Checked_vector changes the behaviour of operator[] to use at instead in PPP_support.h.

As has already been stated in comments and the other answer, the std::vector does not do bounds checking for operator[]

std::vector's operator[] doesn't perform any validity check on the index. If it is out-of-bounds, then that's a violation of operator[]'s preconditions and therefore undefined behavior. Undefined behavior means that anything can happen. Throwing an exception is permissible (in in debug builds the compiler might to that), but producing non-sense or crashing are just as valid.

std::vector also has the .at member function which doesn't have the precondition that the index is in-bounds and instead throws a std::out_of_bounds exception if the index is not in-bounds. It seems that you wanted to use that:

    for(int i = 0; i <= items.size(); ++i){ // out of range
        std::cout << i << " -> " << items.at(i) << std::endl;
    }

However, in general .at is not used often. Accessing the vector out-of-bounds is usually an indicator for a program logic flaw that shouldn't happen at all and not just an exceptional execution flow that is intended to happen. Exceptions are not usually a solution to a programming error.

Mac M1. I learn C++ by Bjarne Stroustrup's book. He show the similar example in his "Programming. Principles and Practice Using C++" book (chapter 5.6.2). Also he writes this exception (out_of_range) is to be occurred.

clang++ --version
Apple clang version 16.0.0 (clang-1600.0.26.4)
Target: arm64-apple-darwin24.0.0
Thread model: posix

My code:

#include <iostream>
#include <vector>

int main(){
    try{
        std::vector<int> items;

        constexpr int size = 5;

        for(int i = 0; i < size; ++i){
            items.push_back(i * 10);
        }

        for(int i = 0; i <= items.size(); ++i){ // out of range!
            std::cout << i << " -> " << items[i] << std::endl;
        }
        std::cout << "Success!" << std::endl;
    }
    catch (std::out_of_range){
        std::cerr << "Range error!" << std::endl;
    }
    catch(...){
        std::cerr << "Something wrong..." << std::endl;
    }
}

Compilation command:

clang++ -std=c++20 main.cpp

Result:

./a.out 
0 -> 0
1 -> 10
2 -> 20
3 -> 30
4 -> 40
5 -> 0
Success!

I've expected to get the out of range exception but it wasn't happened. Why?

Mac M1. I learn C++ by Bjarne Stroustrup's book. He show the similar example in his "Programming. Principles and Practice Using C++" book (chapter 5.6.2). Also he writes this exception (out_of_range) is to be occurred.

clang++ --version
Apple clang version 16.0.0 (clang-1600.0.26.4)
Target: arm64-apple-darwin24.0.0
Thread model: posix

My code:

#include <iostream>
#include <vector>

int main(){
    try{
        std::vector<int> items;

        constexpr int size = 5;

        for(int i = 0; i < size; ++i){
            items.push_back(i * 10);
        }

        for(int i = 0; i <= items.size(); ++i){ // out of range!
            std::cout << i << " -> " << items[i] << std::endl;
        }
        std::cout << "Success!" << std::endl;
    }
    catch (std::out_of_range){
        std::cerr << "Range error!" << std::endl;
    }
    catch(...){
        std::cerr << "Something wrong..." << std::endl;
    }
}

Compilation command:

clang++ -std=c++20 main.cpp

Result:

./a.out 
0 -> 0
1 -> 10
2 -> 20
3 -> 30
4 -> 40
5 -> 0
Success!

I've expected to get the out of range exception but it wasn't happened. Why?

Share Improve this question edited Nov 17, 2024 at 12:40 Andrey Bushman asked Nov 17, 2024 at 12:05 Andrey BushmanAndrey Bushman 12.5k23 gold badges103 silver badges210 bronze badges 8
  • @AhmedAEK learn.microsoft/en-us/cpp/standard-library/… – Andrey Bushman Commented Nov 17, 2024 at 12:12
  • If you read the out_of_range docs it is thrown by the .at member functions, not the brackets operators, those are not checked, in general you shouldn't expect c++ to put unnecessary checks on the hot paths – Ahmed AEK Commented Nov 17, 2024 at 12:15
  • 3 @AndreyBushman If it says what you say it does then it is simply wrong. vector::at throws std::out_of_range not vector::operator[]. – john Commented Nov 17, 2024 at 12:19
  • 1 Use vector's .at() method – Pepijn Kramer Commented Nov 17, 2024 at 12:29
  • 1 You are right the book does say that, it is likely a mistake as bjarne didn't create vector (he didn't even create the STL library which the modern standard library is based on), in any case there are proposals to have C++ do bound checks in the future, but it won't throw an exception and only "error out" in debug mode ..... which a lot of implementations already do anyway. – Ahmed AEK Commented Nov 17, 2024 at 12:32
 |  Show 3 more comments

2 Answers 2

Reset to default 5

I believe you are confusing Bjarne Stroustrup's vector and std::vector.

Stroustrup's PPPheaders.h uses a #define vector Checked_vector. A Checked_vector changes the behaviour of operator[] to use at instead in PPP_support.h.

As has already been stated in comments and the other answer, the std::vector does not do bounds checking for operator[]

std::vector's operator[] doesn't perform any validity check on the index. If it is out-of-bounds, then that's a violation of operator[]'s preconditions and therefore undefined behavior. Undefined behavior means that anything can happen. Throwing an exception is permissible (in in debug builds the compiler might to that), but producing non-sense or crashing are just as valid.

std::vector also has the .at member function which doesn't have the precondition that the index is in-bounds and instead throws a std::out_of_bounds exception if the index is not in-bounds. It seems that you wanted to use that:

    for(int i = 0; i <= items.size(); ++i){ // out of range
        std::cout << i << " -> " << items.at(i) << std::endl;
    }

However, in general .at is not used often. Accessing the vector out-of-bounds is usually an indicator for a program logic flaw that shouldn't happen at all and not just an exceptional execution flow that is intended to happen. Exceptions are not usually a solution to a programming error.

本文标签: cstdvector why outofrange error doesn39t happenStack Overflow