Access elements in std::string where positon of string is greater than its size The 2019 Stack...

Does a dangling wire really electrocute me if I'm standing in water?

Where to refill my bottle in India?

The difference between dialogue marks

Apparent duplicates between Haynes service instructions and MOT

How technical should a Scrum Master be to effectively remove impediments?

A poker game description that does not feel gimmicky

How to save as into a customized destination on macOS?

Worn-tile Scrabble

Why is the Constellation's nose gear so long?

Falsification in Math vs Science

How to notate time signature switching consistently every measure

Resizing object distorts it (Illustrator CC 2018)

Why not take a picture of a closer black hole?

What to do when moving next to a bird sanctuary with a loosely-domesticated cat?

Can someone be penalized for an "unlawful" act if no penalty is specified?

How are circuits which use complex ICs normally simulated?

Lightning Grid - Columns and Rows?

Is an up-to-date browser secure on an out-of-date OS?

How to type this arrow in math mode?

Feature engineering suggestion required

slides for 30min~1hr skype tenure track application interview

What tool would a Roman-age civilization have for the breaking of silver and other metals into dust?

What is the most effective way of iterating a std::vector and why?

Deal with toxic manager when you can't quit



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



The 2019 Stack Overflow Developer Survey Results Are InWhat's the best way to trim std::string?How to convert std::string to lower case?How to convert a std::string to const char* or char*?std::wstring VS std::stringDoes std::string find require that pos be less than the string size?Are the days of passing const std::string & as a parameter over?Is a std::string implementation conformant where 's.c_str() + s.size()' is not necessarily the same as '&s[s.size()]'?Why is f(i = -1, i = -1) undefined behavior?In C++11 and beyond does std::string::operator[] do bounds checking?What made i = i++ + 1; legal in C++17?





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







23















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




















  • 5





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

    – KostasRim
    yesterday








  • 6





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

    – Max Langhof
    yesterday








  • 7





    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
    yesterday






  • 7





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

    – Max Langhof
    yesterday






  • 2





    VS (in debug builds) is within it's rights to checks bounds and throw in [], because undefined behaviour allows anything.

    – Caleth
    yesterday


















23















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




















  • 5





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

    – KostasRim
    yesterday








  • 6





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

    – Max Langhof
    yesterday








  • 7





    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
    yesterday






  • 7





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

    – Max Langhof
    yesterday






  • 2





    VS (in debug builds) is within it's rights to checks bounds and throw in [], because undefined behaviour allows anything.

    – Caleth
    yesterday














23












23








23


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 yesterday









Mooing Duck

47.4k1173132




47.4k1173132










asked yesterday









AImx1AImx1

490219




490219








  • 5





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

    – KostasRim
    yesterday








  • 6





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

    – Max Langhof
    yesterday








  • 7





    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
    yesterday






  • 7





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

    – Max Langhof
    yesterday






  • 2





    VS (in debug builds) is within it's rights to checks bounds and throw in [], because undefined behaviour allows anything.

    – Caleth
    yesterday














  • 5





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

    – KostasRim
    yesterday








  • 6





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

    – Max Langhof
    yesterday








  • 7





    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
    yesterday






  • 7





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

    – Max Langhof
    yesterday






  • 2





    VS (in debug builds) is within it's rights to checks bounds and throw in [], because undefined behaviour allows anything.

    – Caleth
    yesterday








5




5





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

– KostasRim
yesterday







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

– KostasRim
yesterday






6




6





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

– Max Langhof
yesterday







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

– Max Langhof
yesterday






7




7





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
yesterday





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
yesterday




7




7





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

– Max Langhof
yesterday





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

– Max Langhof
yesterday




2




2





VS (in debug builds) is within it's rights to checks bounds and throw in [], because undefined behaviour allows anything.

– Caleth
yesterday





VS (in debug builds) is within it's rights to checks bounds and throw in [], because undefined behaviour allows anything.

– Caleth
yesterday












4 Answers
4






active

oldest

votes


















35














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


























  • Great explanation. Also a great example how explaining unsupported cases (>size) leads to harder to follow specs. 'otherwise' should have read 'if pos==size'

    – xtofl
    22 hours ago



















21














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 '' 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

































      2














      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





















      • 3





        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
        yesterday













      • 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
        yesterday








      • 2





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

        – KostasRim
        yesterday






      • 3





        @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
        yesterday













      • Also, putting aside the _LIBCPP_ASSERT, what this code snippet really shows is there is no test like if (__pos >= size()) return _CharT(), which is what would be needed for the behaviour the original question was expecting. Without a test like this, the only way _CharT() could be returned is if it is stored in the buffer pointed to by data(). Obviously this can't the case for all possible values of __pos, unless the buffer takes up all the memory on your computer!

        – Arthur Tacca
        yesterday














      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









      35














      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


























      • Great explanation. Also a great example how explaining unsupported cases (>size) leads to harder to follow specs. 'otherwise' should have read 'if pos==size'

        – xtofl
        22 hours ago
















      35














      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


























      • Great explanation. Also a great example how explaining unsupported cases (>size) leads to harder to follow specs. 'otherwise' should have read 'if pos==size'

        – xtofl
        22 hours ago














      35












      35








      35







      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 yesterday

























      answered yesterday









      user463035818user463035818

      18.8k42971




      18.8k42971













      • Great explanation. Also a great example how explaining unsupported cases (>size) leads to harder to follow specs. 'otherwise' should have read 'if pos==size'

        – xtofl
        22 hours ago



















      • Great explanation. Also a great example how explaining unsupported cases (>size) leads to harder to follow specs. 'otherwise' should have read 'if pos==size'

        – xtofl
        22 hours ago

















      Great explanation. Also a great example how explaining unsupported cases (>size) leads to harder to follow specs. 'otherwise' should have read 'if pos==size'

      – xtofl
      22 hours ago





      Great explanation. Also a great example how explaining unsupported cases (>size) leads to harder to follow specs. 'otherwise' should have read 'if pos==size'

      – xtofl
      22 hours ago













      21














      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 '' into it.






      share|improve this answer






























        21














        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 '' into it.






        share|improve this answer




























          21












          21








          21







          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 '' 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 '' into it.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited yesterday









          Mooing Duck

          47.4k1173132




          47.4k1173132










          answered yesterday









          rustyxrustyx

          33.4k8100144




          33.4k8100144























              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 yesterday









                  Raimund Krämer

                  710425




                  710425










                  answered yesterday









                  YolaYola

                  11.5k64773




                  11.5k64773























                      2














                      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





















                      • 3





                        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
                        yesterday













                      • 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
                        yesterday








                      • 2





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

                        – KostasRim
                        yesterday






                      • 3





                        @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
                        yesterday













                      • Also, putting aside the _LIBCPP_ASSERT, what this code snippet really shows is there is no test like if (__pos >= size()) return _CharT(), which is what would be needed for the behaviour the original question was expecting. Without a test like this, the only way _CharT() could be returned is if it is stored in the buffer pointed to by data(). Obviously this can't the case for all possible values of __pos, unless the buffer takes up all the memory on your computer!

                        – Arthur Tacca
                        yesterday


















                      2














                      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





















                      • 3





                        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
                        yesterday













                      • 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
                        yesterday








                      • 2





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

                        – KostasRim
                        yesterday






                      • 3





                        @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
                        yesterday













                      • Also, putting aside the _LIBCPP_ASSERT, what this code snippet really shows is there is no test like if (__pos >= size()) return _CharT(), which is what would be needed for the behaviour the original question was expecting. Without a test like this, the only way _CharT() could be returned is if it is stored in the buffer pointed to by data(). Obviously this can't the case for all possible values of __pos, unless the buffer takes up all the memory on your computer!

                        – Arthur Tacca
                        yesterday
















                      2












                      2








                      2







                      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 yesterday

























                      answered yesterday









                      KostasRimKostasRim

                      1,5821926




                      1,5821926








                      • 3





                        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
                        yesterday













                      • 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
                        yesterday








                      • 2





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

                        – KostasRim
                        yesterday






                      • 3





                        @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
                        yesterday













                      • Also, putting aside the _LIBCPP_ASSERT, what this code snippet really shows is there is no test like if (__pos >= size()) return _CharT(), which is what would be needed for the behaviour the original question was expecting. Without a test like this, the only way _CharT() could be returned is if it is stored in the buffer pointed to by data(). Obviously this can't the case for all possible values of __pos, unless the buffer takes up all the memory on your computer!

                        – Arthur Tacca
                        yesterday
















                      • 3





                        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
                        yesterday













                      • 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
                        yesterday








                      • 2





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

                        – KostasRim
                        yesterday






                      • 3





                        @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
                        yesterday













                      • Also, putting aside the _LIBCPP_ASSERT, what this code snippet really shows is there is no test like if (__pos >= size()) return _CharT(), which is what would be needed for the behaviour the original question was expecting. Without a test like this, the only way _CharT() could be returned is if it is stored in the buffer pointed to by data(). Obviously this can't the case for all possible values of __pos, unless the buffer takes up all the memory on your computer!

                        – Arthur Tacca
                        yesterday










                      3




                      3





                      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
                      yesterday







                      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
                      yesterday















                      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
                      yesterday







                      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
                      yesterday






                      2




                      2





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

                      – KostasRim
                      yesterday





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

                      – KostasRim
                      yesterday




                      3




                      3





                      @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
                      yesterday







                      @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
                      yesterday















                      Also, putting aside the _LIBCPP_ASSERT, what this code snippet really shows is there is no test like if (__pos >= size()) return _CharT(), which is what would be needed for the behaviour the original question was expecting. Without a test like this, the only way _CharT() could be returned is if it is stored in the buffer pointed to by data(). Obviously this can't the case for all possible values of __pos, unless the buffer takes up all the memory on your computer!

                      – Arthur Tacca
                      yesterday







                      Also, putting aside the _LIBCPP_ASSERT, what this code snippet really shows is there is no test like if (__pos >= size()) return _CharT(), which is what would be needed for the behaviour the original question was expecting. Without a test like this, the only way _CharT() could be returned is if it is stored in the buffer pointed to by data(). Obviously this can't the case for all possible values of __pos, unless the buffer takes up all the memory on your computer!

                      – Arthur Tacca
                      yesterday




















                      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

                      VNC viewer RFB protocol error: bad desktop size 0x0I Cannot Type the Key 'd' (lowercase) in VNC Viewer...

                      Tribunal Administrativo e Fiscal de Mirandela Referências Menu de...

                      looking for continuous Screen Capture for retroactivly reproducing errors, timeback machineRolling desktop...