Access elements in std::string where positon of string is greater than its size





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







16















In case of std::string, if we access an element where (element position) > (size of string) the standard says that it returns a reference to an object of type charT with value charT().



const_reference operator(size_type pos) const;
reference operator(size_type pos);



Expects: pos <= size().



Returns: *(begin() + pos) if pos < size(). Otherwise, returns a
reference to an object of type charT with value charT(), where
modifying the object to any value other than charT() leads to
undefined behavior.




http://eel.is/c++draft/strings#string.access-1



Unfortunately I couldn't reason about this, it would have been better if it has been Undefined Behavior.



Can somebody explain the rationale behind this?










share|improve this question




















  • 1





    @Yola you mean because operator has to check if the index is < size in any case?

    – user463035818
    8 hours ago






  • 4





    @user463035818 no that's not true. Subscript operator does not perform a check. string::at() does and for that reason it throws

    – KostasRim
    8 hours ago








  • 4





    Doesn't violating "Expects: pos <= size()" lead to UB straight away? The "Otherwise" refers only to the pos == size case, no?

    – Max Langhof
    8 hours ago








  • 5





    exactly I think the crux is "Expects: pos <= size()." if you dont follow the precondition you are in UB land anyhow, so it is just about accesing the "end" of the string

    – user463035818
    8 hours ago






  • 5





    @AImx1 Where does the standard say that violating an "Expects" clause is anything other than UB?

    – Max Langhof
    8 hours ago


















16















In case of std::string, if we access an element where (element position) > (size of string) the standard says that it returns a reference to an object of type charT with value charT().



const_reference operator(size_type pos) const;
reference operator(size_type pos);



Expects: pos <= size().



Returns: *(begin() + pos) if pos < size(). Otherwise, returns a
reference to an object of type charT with value charT(), where
modifying the object to any value other than charT() leads to
undefined behavior.




http://eel.is/c++draft/strings#string.access-1



Unfortunately I couldn't reason about this, it would have been better if it has been Undefined Behavior.



Can somebody explain the rationale behind this?










share|improve this question




















  • 1





    @Yola you mean because operator has to check if the index is < size in any case?

    – user463035818
    8 hours ago






  • 4





    @user463035818 no that's not true. Subscript operator does not perform a check. string::at() does and for that reason it throws

    – KostasRim
    8 hours ago








  • 4





    Doesn't violating "Expects: pos <= size()" lead to UB straight away? The "Otherwise" refers only to the pos == size case, no?

    – Max Langhof
    8 hours ago








  • 5





    exactly I think the crux is "Expects: pos <= size()." if you dont follow the precondition you are in UB land anyhow, so it is just about accesing the "end" of the string

    – user463035818
    8 hours ago






  • 5





    @AImx1 Where does the standard say that violating an "Expects" clause is anything other than UB?

    – Max Langhof
    8 hours ago














16












16








16


2






In case of std::string, if we access an element where (element position) > (size of string) the standard says that it returns a reference to an object of type charT with value charT().



const_reference operator(size_type pos) const;
reference operator(size_type pos);



Expects: pos <= size().



Returns: *(begin() + pos) if pos < size(). Otherwise, returns a
reference to an object of type charT with value charT(), where
modifying the object to any value other than charT() leads to
undefined behavior.




http://eel.is/c++draft/strings#string.access-1



Unfortunately I couldn't reason about this, it would have been better if it has been Undefined Behavior.



Can somebody explain the rationale behind this?










share|improve this question
















In case of std::string, if we access an element where (element position) > (size of string) the standard says that it returns a reference to an object of type charT with value charT().



const_reference operator(size_type pos) const;
reference operator(size_type pos);



Expects: pos <= size().



Returns: *(begin() + pos) if pos < size(). Otherwise, returns a
reference to an object of type charT with value charT(), where
modifying the object to any value other than charT() leads to
undefined behavior.




http://eel.is/c++draft/strings#string.access-1



Unfortunately I couldn't reason about this, it would have been better if it has been Undefined Behavior.



Can somebody explain the rationale behind this?







c++ string c++11 language-lawyer






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 8 hours ago









Samer Tufail

1,628922




1,628922










asked 9 hours ago









AImx1AImx1

455217




455217








  • 1





    @Yola you mean because operator has to check if the index is < size in any case?

    – user463035818
    8 hours ago






  • 4





    @user463035818 no that's not true. Subscript operator does not perform a check. string::at() does and for that reason it throws

    – KostasRim
    8 hours ago








  • 4





    Doesn't violating "Expects: pos <= size()" lead to UB straight away? The "Otherwise" refers only to the pos == size case, no?

    – Max Langhof
    8 hours ago








  • 5





    exactly I think the crux is "Expects: pos <= size()." if you dont follow the precondition you are in UB land anyhow, so it is just about accesing the "end" of the string

    – user463035818
    8 hours ago






  • 5





    @AImx1 Where does the standard say that violating an "Expects" clause is anything other than UB?

    – Max Langhof
    8 hours ago














  • 1





    @Yola you mean because operator has to check if the index is < size in any case?

    – user463035818
    8 hours ago






  • 4





    @user463035818 no that's not true. Subscript operator does not perform a check. string::at() does and for that reason it throws

    – KostasRim
    8 hours ago








  • 4





    Doesn't violating "Expects: pos <= size()" lead to UB straight away? The "Otherwise" refers only to the pos == size case, no?

    – Max Langhof
    8 hours ago








  • 5





    exactly I think the crux is "Expects: pos <= size()." if you dont follow the precondition you are in UB land anyhow, so it is just about accesing the "end" of the string

    – user463035818
    8 hours ago






  • 5





    @AImx1 Where does the standard say that violating an "Expects" clause is anything other than UB?

    – Max Langhof
    8 hours ago








1




1





@Yola you mean because operator has to check if the index is < size in any case?

– user463035818
8 hours ago





@Yola you mean because operator has to check if the index is < size in any case?

– user463035818
8 hours ago




4




4





@user463035818 no that's not true. Subscript operator does not perform a check. string::at() does and for that reason it throws

– KostasRim
8 hours ago







@user463035818 no that's not true. Subscript operator does not perform a check. string::at() does and for that reason it throws

– KostasRim
8 hours ago






4




4





Doesn't violating "Expects: pos <= size()" lead to UB straight away? The "Otherwise" refers only to the pos == size case, no?

– Max Langhof
8 hours ago







Doesn't violating "Expects: pos <= size()" lead to UB straight away? The "Otherwise" refers only to the pos == size case, no?

– Max Langhof
8 hours ago






5




5





exactly I think the crux is "Expects: pos <= size()." if you dont follow the precondition you are in UB land anyhow, so it is just about accesing the "end" of the string

– user463035818
8 hours ago





exactly I think the crux is "Expects: pos <= size()." if you dont follow the precondition you are in UB land anyhow, so it is just about accesing the "end" of the string

– user463035818
8 hours ago




5




5





@AImx1 Where does the standard say that violating an "Expects" clause is anything other than UB?

– Max Langhof
8 hours ago





@AImx1 Where does the standard say that violating an "Expects" clause is anything other than UB?

– Max Langhof
8 hours ago












4 Answers
4






active

oldest

votes


















22














You have to consider the full specs.



First of all:




Expects: pos <= size().




If you dont follow the precondition you have undefined behaviour anyhow. Now...




Returns: *(begin() + pos) if pos < size(). Otherwise, returns a
reference to an object of type charT with value charT(), where
modifying the object to any value other than charT() leads to
undefined behavior.




The only (valid) case that "otherwise" refers to is when pos == size(). And that is probably to emulate c string behaviour that have a some_string[size] element that can be accessed. Note that charT() is typically just ''.



PS: One might think that to implement the specification, operator would have to check if pos == size. However, if the underlying character array has a charT() at the end of the string, then you get the described behaviour basically for free. Hence, what seems a little different from "usual" access into an array is actually just that.






share|improve this answer

































    14














    Statement 1 is the precondition for statement 2:





    1. Expects: pos <= size().



    2. Returns: *(begin() + pos) if pos < size().



      Otherwise (so here the only viable possibility is pos == size()), returns a reference to an object of type charT with value charT() (i.e. ''), where modifying the object to any value other than charT() leads to undefined behavior.






    str[str.size()] basically points to the null-terminator character. You can read and write it, but you may only write a null into it.






    share|improve this answer































      14














      The operator expects pos to be less than or equal to size(), so if it is not less, then it is expected to be equal.






      share|improve this answer

































        1














        Additionally to the previous answers please take a look at the libcxx (the llvm implementation) defines std::string::operator like:



        template <class _CharT, class _Traits, class _Allocator>
        inline
        typename basic_string<_CharT, _Traits, _Allocator>::const_reference
        basic_string<_CharT, _Traits, _Allocator>::operator(size_type __pos) const _NOEXCEPT
        {
        _LIBCPP_ASSERT(__pos <= size(), "string index out of bounds");
        return *(data() + __pos);
        }

        template <class _CharT, class _Traits, class _Allocator>
        inline
        typename basic_string<_CharT, _Traits, _Allocator>::reference
        basic_string<_CharT, _Traits, _Allocator>::operator(size_type __pos) _NOEXCEPT
        {
        _LIBCPP_ASSERT(__pos <= size(), "string index out of bounds");
        return *(__get_pointer() + __pos);
        }


        Take a look at the .at() that properly throws instead.



        template <class _CharT, class _Traits, class _Allocator>
        typename basic_string<_CharT, _Traits, _Allocator>::const_reference
        basic_string<_CharT, _Traits, _Allocator>::at(size_type __n) const
        {
        if (__n >= size())
        this->__throw_out_of_range();
        return (*this)[__n];
        }


        As you can, in the first case, there is a runtime assert(thanks t.niese for pointing out) which is triggered only in debug mode whereas the second will always throw, regardless of the build options of the library.






        share|improve this answer





















        • 2





          That's not a static assert it is a runtime assert. A static_assert is something that is check at compile time, and a static assert is done for both release and debug builds.

          – t.niese
          8 hours ago













        • Wow thanks for catching that up! You are absolutely right ;) made an edit!

          – KostasRim
          8 hours ago













        • std::string name = "StackOverflow"; std::cout << name[100]; @t.niese If it a run time assert, why does the below code doesn't crash?

          – AImx1
          8 hours ago








        • 1





          @AImx1 cause you didn't specify that you want the debug build when building the library?

          – KostasRim
          8 hours ago






        • 2





          @AImx1 because the standard says that name[100] is undefined behavior, and not that it must throw. _LIBCPP_ASSERT is a debugging assert that has to be explicitly enabled and is not automatically enable for regular debug builds, and it is run-time dependent llvm: DebugMode

          – t.niese
          8 hours ago














        Your Answer






        StackExchange.ifUsing("editor", function () {
        StackExchange.using("externalEditor", function () {
        StackExchange.using("snippets", function () {
        StackExchange.snippets.init();
        });
        });
        }, "code-snippets");

        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "1"
        };
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function() {
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled) {
        StackExchange.using("snippets", function() {
        createEditor();
        });
        }
        else {
        createEditor();
        }
        });

        function createEditor() {
        StackExchange.prepareEditor({
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: true,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });














        draft saved

        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55588104%2faccess-elements-in-stdstring-where-positon-of-string-is-greater-than-its-size%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        4 Answers
        4






        active

        oldest

        votes








        4 Answers
        4






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        22














        You have to consider the full specs.



        First of all:




        Expects: pos <= size().




        If you dont follow the precondition you have undefined behaviour anyhow. Now...




        Returns: *(begin() + pos) if pos < size(). Otherwise, returns a
        reference to an object of type charT with value charT(), where
        modifying the object to any value other than charT() leads to
        undefined behavior.




        The only (valid) case that "otherwise" refers to is when pos == size(). And that is probably to emulate c string behaviour that have a some_string[size] element that can be accessed. Note that charT() is typically just ''.



        PS: One might think that to implement the specification, operator would have to check if pos == size. However, if the underlying character array has a charT() at the end of the string, then you get the described behaviour basically for free. Hence, what seems a little different from "usual" access into an array is actually just that.






        share|improve this answer






























          22














          You have to consider the full specs.



          First of all:




          Expects: pos <= size().




          If you dont follow the precondition you have undefined behaviour anyhow. Now...




          Returns: *(begin() + pos) if pos < size(). Otherwise, returns a
          reference to an object of type charT with value charT(), where
          modifying the object to any value other than charT() leads to
          undefined behavior.




          The only (valid) case that "otherwise" refers to is when pos == size(). And that is probably to emulate c string behaviour that have a some_string[size] element that can be accessed. Note that charT() is typically just ''.



          PS: One might think that to implement the specification, operator would have to check if pos == size. However, if the underlying character array has a charT() at the end of the string, then you get the described behaviour basically for free. Hence, what seems a little different from "usual" access into an array is actually just that.






          share|improve this answer




























            22












            22








            22







            You have to consider the full specs.



            First of all:




            Expects: pos <= size().




            If you dont follow the precondition you have undefined behaviour anyhow. Now...




            Returns: *(begin() + pos) if pos < size(). Otherwise, returns a
            reference to an object of type charT with value charT(), where
            modifying the object to any value other than charT() leads to
            undefined behavior.




            The only (valid) case that "otherwise" refers to is when pos == size(). And that is probably to emulate c string behaviour that have a some_string[size] element that can be accessed. Note that charT() is typically just ''.



            PS: One might think that to implement the specification, operator would have to check if pos == size. However, if the underlying character array has a charT() at the end of the string, then you get the described behaviour basically for free. Hence, what seems a little different from "usual" access into an array is actually just that.






            share|improve this answer















            You have to consider the full specs.



            First of all:




            Expects: pos <= size().




            If you dont follow the precondition you have undefined behaviour anyhow. Now...




            Returns: *(begin() + pos) if pos < size(). Otherwise, returns a
            reference to an object of type charT with value charT(), where
            modifying the object to any value other than charT() leads to
            undefined behavior.




            The only (valid) case that "otherwise" refers to is when pos == size(). And that is probably to emulate c string behaviour that have a some_string[size] element that can be accessed. Note that charT() is typically just ''.



            PS: One might think that to implement the specification, operator would have to check if pos == size. However, if the underlying character array has a charT() at the end of the string, then you get the described behaviour basically for free. Hence, what seems a little different from "usual" access into an array is actually just that.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 8 hours ago

























            answered 8 hours ago









            user463035818user463035818

            18.7k42870




            18.7k42870

























                14














                Statement 1 is the precondition for statement 2:





                1. Expects: pos <= size().



                2. Returns: *(begin() + pos) if pos < size().



                  Otherwise (so here the only viable possibility is pos == size()), returns a reference to an object of type charT with value charT() (i.e. ''), where modifying the object to any value other than charT() leads to undefined behavior.






                str[str.size()] basically points to the null-terminator character. You can read and write it, but you may only write a null into it.






                share|improve this answer




























                  14














                  Statement 1 is the precondition for statement 2:





                  1. Expects: pos <= size().



                  2. Returns: *(begin() + pos) if pos < size().



                    Otherwise (so here the only viable possibility is pos == size()), returns a reference to an object of type charT with value charT() (i.e. ''), where modifying the object to any value other than charT() leads to undefined behavior.






                  str[str.size()] basically points to the null-terminator character. You can read and write it, but you may only write a null into it.






                  share|improve this answer


























                    14












                    14








                    14







                    Statement 1 is the precondition for statement 2:





                    1. Expects: pos <= size().



                    2. Returns: *(begin() + pos) if pos < size().



                      Otherwise (so here the only viable possibility is pos == size()), returns a reference to an object of type charT with value charT() (i.e. ''), where modifying the object to any value other than charT() leads to undefined behavior.






                    str[str.size()] basically points to the null-terminator character. You can read and write it, but you may only write a null into it.






                    share|improve this answer













                    Statement 1 is the precondition for statement 2:





                    1. Expects: pos <= size().



                    2. Returns: *(begin() + pos) if pos < size().



                      Otherwise (so here the only viable possibility is pos == size()), returns a reference to an object of type charT with value charT() (i.e. ''), where modifying the object to any value other than charT() leads to undefined behavior.






                    str[str.size()] basically points to the null-terminator character. You can read and write it, but you may only write a null into it.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered 8 hours ago









                    rustyxrustyx

                    33.2k8100144




                    33.2k8100144























                        14














                        The operator expects pos to be less than or equal to size(), so if it is not less, then it is expected to be equal.






                        share|improve this answer






























                          14














                          The operator expects pos to be less than or equal to size(), so if it is not less, then it is expected to be equal.






                          share|improve this answer




























                            14












                            14








                            14







                            The operator expects pos to be less than or equal to size(), so if it is not less, then it is expected to be equal.






                            share|improve this answer















                            The operator expects pos to be less than or equal to size(), so if it is not less, then it is expected to be equal.







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited 7 hours ago









                            Raimund Krämer

                            710425




                            710425










                            answered 8 hours ago









                            YolaYola

                            11.4k64773




                            11.4k64773























                                1














                                Additionally to the previous answers please take a look at the libcxx (the llvm implementation) defines std::string::operator like:



                                template <class _CharT, class _Traits, class _Allocator>
                                inline
                                typename basic_string<_CharT, _Traits, _Allocator>::const_reference
                                basic_string<_CharT, _Traits, _Allocator>::operator(size_type __pos) const _NOEXCEPT
                                {
                                _LIBCPP_ASSERT(__pos <= size(), "string index out of bounds");
                                return *(data() + __pos);
                                }

                                template <class _CharT, class _Traits, class _Allocator>
                                inline
                                typename basic_string<_CharT, _Traits, _Allocator>::reference
                                basic_string<_CharT, _Traits, _Allocator>::operator(size_type __pos) _NOEXCEPT
                                {
                                _LIBCPP_ASSERT(__pos <= size(), "string index out of bounds");
                                return *(__get_pointer() + __pos);
                                }


                                Take a look at the .at() that properly throws instead.



                                template <class _CharT, class _Traits, class _Allocator>
                                typename basic_string<_CharT, _Traits, _Allocator>::const_reference
                                basic_string<_CharT, _Traits, _Allocator>::at(size_type __n) const
                                {
                                if (__n >= size())
                                this->__throw_out_of_range();
                                return (*this)[__n];
                                }


                                As you can, in the first case, there is a runtime assert(thanks t.niese for pointing out) which is triggered only in debug mode whereas the second will always throw, regardless of the build options of the library.






                                share|improve this answer





















                                • 2





                                  That's not a static assert it is a runtime assert. A static_assert is something that is check at compile time, and a static assert is done for both release and debug builds.

                                  – t.niese
                                  8 hours ago













                                • Wow thanks for catching that up! You are absolutely right ;) made an edit!

                                  – KostasRim
                                  8 hours ago













                                • std::string name = "StackOverflow"; std::cout << name[100]; @t.niese If it a run time assert, why does the below code doesn't crash?

                                  – AImx1
                                  8 hours ago








                                • 1





                                  @AImx1 cause you didn't specify that you want the debug build when building the library?

                                  – KostasRim
                                  8 hours ago






                                • 2





                                  @AImx1 because the standard says that name[100] is undefined behavior, and not that it must throw. _LIBCPP_ASSERT is a debugging assert that has to be explicitly enabled and is not automatically enable for regular debug builds, and it is run-time dependent llvm: DebugMode

                                  – t.niese
                                  8 hours ago


















                                1














                                Additionally to the previous answers please take a look at the libcxx (the llvm implementation) defines std::string::operator like:



                                template <class _CharT, class _Traits, class _Allocator>
                                inline
                                typename basic_string<_CharT, _Traits, _Allocator>::const_reference
                                basic_string<_CharT, _Traits, _Allocator>::operator(size_type __pos) const _NOEXCEPT
                                {
                                _LIBCPP_ASSERT(__pos <= size(), "string index out of bounds");
                                return *(data() + __pos);
                                }

                                template <class _CharT, class _Traits, class _Allocator>
                                inline
                                typename basic_string<_CharT, _Traits, _Allocator>::reference
                                basic_string<_CharT, _Traits, _Allocator>::operator(size_type __pos) _NOEXCEPT
                                {
                                _LIBCPP_ASSERT(__pos <= size(), "string index out of bounds");
                                return *(__get_pointer() + __pos);
                                }


                                Take a look at the .at() that properly throws instead.



                                template <class _CharT, class _Traits, class _Allocator>
                                typename basic_string<_CharT, _Traits, _Allocator>::const_reference
                                basic_string<_CharT, _Traits, _Allocator>::at(size_type __n) const
                                {
                                if (__n >= size())
                                this->__throw_out_of_range();
                                return (*this)[__n];
                                }


                                As you can, in the first case, there is a runtime assert(thanks t.niese for pointing out) which is triggered only in debug mode whereas the second will always throw, regardless of the build options of the library.






                                share|improve this answer





















                                • 2





                                  That's not a static assert it is a runtime assert. A static_assert is something that is check at compile time, and a static assert is done for both release and debug builds.

                                  – t.niese
                                  8 hours ago













                                • Wow thanks for catching that up! You are absolutely right ;) made an edit!

                                  – KostasRim
                                  8 hours ago













                                • std::string name = "StackOverflow"; std::cout << name[100]; @t.niese If it a run time assert, why does the below code doesn't crash?

                                  – AImx1
                                  8 hours ago








                                • 1





                                  @AImx1 cause you didn't specify that you want the debug build when building the library?

                                  – KostasRim
                                  8 hours ago






                                • 2





                                  @AImx1 because the standard says that name[100] is undefined behavior, and not that it must throw. _LIBCPP_ASSERT is a debugging assert that has to be explicitly enabled and is not automatically enable for regular debug builds, and it is run-time dependent llvm: DebugMode

                                  – t.niese
                                  8 hours ago
















                                1












                                1








                                1







                                Additionally to the previous answers please take a look at the libcxx (the llvm implementation) defines std::string::operator like:



                                template <class _CharT, class _Traits, class _Allocator>
                                inline
                                typename basic_string<_CharT, _Traits, _Allocator>::const_reference
                                basic_string<_CharT, _Traits, _Allocator>::operator(size_type __pos) const _NOEXCEPT
                                {
                                _LIBCPP_ASSERT(__pos <= size(), "string index out of bounds");
                                return *(data() + __pos);
                                }

                                template <class _CharT, class _Traits, class _Allocator>
                                inline
                                typename basic_string<_CharT, _Traits, _Allocator>::reference
                                basic_string<_CharT, _Traits, _Allocator>::operator(size_type __pos) _NOEXCEPT
                                {
                                _LIBCPP_ASSERT(__pos <= size(), "string index out of bounds");
                                return *(__get_pointer() + __pos);
                                }


                                Take a look at the .at() that properly throws instead.



                                template <class _CharT, class _Traits, class _Allocator>
                                typename basic_string<_CharT, _Traits, _Allocator>::const_reference
                                basic_string<_CharT, _Traits, _Allocator>::at(size_type __n) const
                                {
                                if (__n >= size())
                                this->__throw_out_of_range();
                                return (*this)[__n];
                                }


                                As you can, in the first case, there is a runtime assert(thanks t.niese for pointing out) which is triggered only in debug mode whereas the second will always throw, regardless of the build options of the library.






                                share|improve this answer















                                Additionally to the previous answers please take a look at the libcxx (the llvm implementation) defines std::string::operator like:



                                template <class _CharT, class _Traits, class _Allocator>
                                inline
                                typename basic_string<_CharT, _Traits, _Allocator>::const_reference
                                basic_string<_CharT, _Traits, _Allocator>::operator(size_type __pos) const _NOEXCEPT
                                {
                                _LIBCPP_ASSERT(__pos <= size(), "string index out of bounds");
                                return *(data() + __pos);
                                }

                                template <class _CharT, class _Traits, class _Allocator>
                                inline
                                typename basic_string<_CharT, _Traits, _Allocator>::reference
                                basic_string<_CharT, _Traits, _Allocator>::operator(size_type __pos) _NOEXCEPT
                                {
                                _LIBCPP_ASSERT(__pos <= size(), "string index out of bounds");
                                return *(__get_pointer() + __pos);
                                }


                                Take a look at the .at() that properly throws instead.



                                template <class _CharT, class _Traits, class _Allocator>
                                typename basic_string<_CharT, _Traits, _Allocator>::const_reference
                                basic_string<_CharT, _Traits, _Allocator>::at(size_type __n) const
                                {
                                if (__n >= size())
                                this->__throw_out_of_range();
                                return (*this)[__n];
                                }


                                As you can, in the first case, there is a runtime assert(thanks t.niese for pointing out) which is triggered only in debug mode whereas the second will always throw, regardless of the build options of the library.







                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited 8 hours ago

























                                answered 8 hours ago









                                KostasRimKostasRim

                                1,5701926




                                1,5701926








                                • 2





                                  That's not a static assert it is a runtime assert. A static_assert is something that is check at compile time, and a static assert is done for both release and debug builds.

                                  – t.niese
                                  8 hours ago













                                • Wow thanks for catching that up! You are absolutely right ;) made an edit!

                                  – KostasRim
                                  8 hours ago













                                • std::string name = "StackOverflow"; std::cout << name[100]; @t.niese If it a run time assert, why does the below code doesn't crash?

                                  – AImx1
                                  8 hours ago








                                • 1





                                  @AImx1 cause you didn't specify that you want the debug build when building the library?

                                  – KostasRim
                                  8 hours ago






                                • 2





                                  @AImx1 because the standard says that name[100] is undefined behavior, and not that it must throw. _LIBCPP_ASSERT is a debugging assert that has to be explicitly enabled and is not automatically enable for regular debug builds, and it is run-time dependent llvm: DebugMode

                                  – t.niese
                                  8 hours ago
















                                • 2





                                  That's not a static assert it is a runtime assert. A static_assert is something that is check at compile time, and a static assert is done for both release and debug builds.

                                  – t.niese
                                  8 hours ago













                                • Wow thanks for catching that up! You are absolutely right ;) made an edit!

                                  – KostasRim
                                  8 hours ago













                                • std::string name = "StackOverflow"; std::cout << name[100]; @t.niese If it a run time assert, why does the below code doesn't crash?

                                  – AImx1
                                  8 hours ago








                                • 1





                                  @AImx1 cause you didn't specify that you want the debug build when building the library?

                                  – KostasRim
                                  8 hours ago






                                • 2





                                  @AImx1 because the standard says that name[100] is undefined behavior, and not that it must throw. _LIBCPP_ASSERT is a debugging assert that has to be explicitly enabled and is not automatically enable for regular debug builds, and it is run-time dependent llvm: DebugMode

                                  – t.niese
                                  8 hours ago










                                2




                                2





                                That's not a static assert it is a runtime assert. A static_assert is something that is check at compile time, and a static assert is done for both release and debug builds.

                                – t.niese
                                8 hours ago







                                That's not a static assert it is a runtime assert. A static_assert is something that is check at compile time, and a static assert is done for both release and debug builds.

                                – t.niese
                                8 hours ago















                                Wow thanks for catching that up! You are absolutely right ;) made an edit!

                                – KostasRim
                                8 hours ago







                                Wow thanks for catching that up! You are absolutely right ;) made an edit!

                                – KostasRim
                                8 hours ago















                                std::string name = "StackOverflow"; std::cout << name[100]; @t.niese If it a run time assert, why does the below code doesn't crash?

                                – AImx1
                                8 hours ago







                                std::string name = "StackOverflow"; std::cout << name[100]; @t.niese If it a run time assert, why does the below code doesn't crash?

                                – AImx1
                                8 hours ago






                                1




                                1





                                @AImx1 cause you didn't specify that you want the debug build when building the library?

                                – KostasRim
                                8 hours ago





                                @AImx1 cause you didn't specify that you want the debug build when building the library?

                                – KostasRim
                                8 hours ago




                                2




                                2





                                @AImx1 because the standard says that name[100] is undefined behavior, and not that it must throw. _LIBCPP_ASSERT is a debugging assert that has to be explicitly enabled and is not automatically enable for regular debug builds, and it is run-time dependent llvm: DebugMode

                                – t.niese
                                8 hours ago







                                @AImx1 because the standard says that name[100] is undefined behavior, and not that it must throw. _LIBCPP_ASSERT is a debugging assert that has to be explicitly enabled and is not automatically enable for regular debug builds, and it is run-time dependent llvm: DebugMode

                                – t.niese
                                8 hours ago




















                                draft saved

                                draft discarded




















































                                Thanks for contributing an answer to Stack Overflow!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55588104%2faccess-elements-in-stdstring-where-positon-of-string-is-greater-than-its-size%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

                                Calculate evaluation metrics using cross_val_predict sklearn

                                Insert data from modal to MySQL (multiple modal on website)