Is std::string guaranteed not to give back memory spontaneously?
Clash Royale CLAN TAG#URR8PPP
up vote
28
down vote
favorite
Is it guaranteed by the standard that std::string
will not give back allocated memory spontaneously if reassigned from a string of a smaller size?
In other words:
std::string str = "Some quite long string, which needs a lot of memory";
str = "";
str = "A new quite long but smaller string"; // Guaranteed to not result in a heap allocation?
I ask because i'm depending on this to avoid heap fragmentation.
c++ language-lawyer heap-memory stdstring
 |Â
show 2 more comments
up vote
28
down vote
favorite
Is it guaranteed by the standard that std::string
will not give back allocated memory spontaneously if reassigned from a string of a smaller size?
In other words:
std::string str = "Some quite long string, which needs a lot of memory";
str = "";
str = "A new quite long but smaller string"; // Guaranteed to not result in a heap allocation?
I ask because i'm depending on this to avoid heap fragmentation.
c++ language-lawyer heap-memory stdstring
if the new string allocation is less than the previous allocation, no allocation occurs. If the new string requires more allocation than the current, a reallocation occurs. Similar to a std::vector.
â Samer Tufail
Sep 25 at 10:19
Strings reuse their buffers when assigned to shorter strings, so in your program there is only one allocation for the string. Unfortunately I can't find conveniently any citation from the standard on mobile
â Fureeish
Sep 25 at 10:20
1
Even if a string did "give back memory spontaneously", that is insufficient to avoid heap fragmentation. A string uses an allocator (by default, an object of typestd::allocator<char>
, but that can be changed) to allocate and deallocate memory, and the allocator may use a lower-level mechanism again (e.g. variants of operatorsnew
anddelete
) to actually allocate and deallocate. If any of those steps elect to not release memory to the lower-level layer, there is potential impact on heap fragmentation.
â Peter
Sep 25 at 10:34
2
If you need to guarantee this behaviour, you can always used your own custom allocator
â doron
Sep 25 at 12:26
10
In my own experience, if I have to utter the phrase "I'm dependent on avoiding heap fragmentation," its a very good time to start considering identifying precise low level requirements, and potentially rolling your own allocation routines.
â Cort Ammon
Sep 25 at 18:06
 |Â
show 2 more comments
up vote
28
down vote
favorite
up vote
28
down vote
favorite
Is it guaranteed by the standard that std::string
will not give back allocated memory spontaneously if reassigned from a string of a smaller size?
In other words:
std::string str = "Some quite long string, which needs a lot of memory";
str = "";
str = "A new quite long but smaller string"; // Guaranteed to not result in a heap allocation?
I ask because i'm depending on this to avoid heap fragmentation.
c++ language-lawyer heap-memory stdstring
Is it guaranteed by the standard that std::string
will not give back allocated memory spontaneously if reassigned from a string of a smaller size?
In other words:
std::string str = "Some quite long string, which needs a lot of memory";
str = "";
str = "A new quite long but smaller string"; // Guaranteed to not result in a heap allocation?
I ask because i'm depending on this to avoid heap fragmentation.
c++ language-lawyer heap-memory stdstring
c++ language-lawyer heap-memory stdstring
edited Sep 25 at 10:57
underscore_d
2,97831842
2,97831842
asked Sep 25 at 10:13
Martin G
8,92465361
8,92465361
if the new string allocation is less than the previous allocation, no allocation occurs. If the new string requires more allocation than the current, a reallocation occurs. Similar to a std::vector.
â Samer Tufail
Sep 25 at 10:19
Strings reuse their buffers when assigned to shorter strings, so in your program there is only one allocation for the string. Unfortunately I can't find conveniently any citation from the standard on mobile
â Fureeish
Sep 25 at 10:20
1
Even if a string did "give back memory spontaneously", that is insufficient to avoid heap fragmentation. A string uses an allocator (by default, an object of typestd::allocator<char>
, but that can be changed) to allocate and deallocate memory, and the allocator may use a lower-level mechanism again (e.g. variants of operatorsnew
anddelete
) to actually allocate and deallocate. If any of those steps elect to not release memory to the lower-level layer, there is potential impact on heap fragmentation.
â Peter
Sep 25 at 10:34
2
If you need to guarantee this behaviour, you can always used your own custom allocator
â doron
Sep 25 at 12:26
10
In my own experience, if I have to utter the phrase "I'm dependent on avoiding heap fragmentation," its a very good time to start considering identifying precise low level requirements, and potentially rolling your own allocation routines.
â Cort Ammon
Sep 25 at 18:06
 |Â
show 2 more comments
if the new string allocation is less than the previous allocation, no allocation occurs. If the new string requires more allocation than the current, a reallocation occurs. Similar to a std::vector.
â Samer Tufail
Sep 25 at 10:19
Strings reuse their buffers when assigned to shorter strings, so in your program there is only one allocation for the string. Unfortunately I can't find conveniently any citation from the standard on mobile
â Fureeish
Sep 25 at 10:20
1
Even if a string did "give back memory spontaneously", that is insufficient to avoid heap fragmentation. A string uses an allocator (by default, an object of typestd::allocator<char>
, but that can be changed) to allocate and deallocate memory, and the allocator may use a lower-level mechanism again (e.g. variants of operatorsnew
anddelete
) to actually allocate and deallocate. If any of those steps elect to not release memory to the lower-level layer, there is potential impact on heap fragmentation.
â Peter
Sep 25 at 10:34
2
If you need to guarantee this behaviour, you can always used your own custom allocator
â doron
Sep 25 at 12:26
10
In my own experience, if I have to utter the phrase "I'm dependent on avoiding heap fragmentation," its a very good time to start considering identifying precise low level requirements, and potentially rolling your own allocation routines.
â Cort Ammon
Sep 25 at 18:06
if the new string allocation is less than the previous allocation, no allocation occurs. If the new string requires more allocation than the current, a reallocation occurs. Similar to a std::vector.
â Samer Tufail
Sep 25 at 10:19
if the new string allocation is less than the previous allocation, no allocation occurs. If the new string requires more allocation than the current, a reallocation occurs. Similar to a std::vector.
â Samer Tufail
Sep 25 at 10:19
Strings reuse their buffers when assigned to shorter strings, so in your program there is only one allocation for the string. Unfortunately I can't find conveniently any citation from the standard on mobile
â Fureeish
Sep 25 at 10:20
Strings reuse their buffers when assigned to shorter strings, so in your program there is only one allocation for the string. Unfortunately I can't find conveniently any citation from the standard on mobile
â Fureeish
Sep 25 at 10:20
1
1
Even if a string did "give back memory spontaneously", that is insufficient to avoid heap fragmentation. A string uses an allocator (by default, an object of type
std::allocator<char>
, but that can be changed) to allocate and deallocate memory, and the allocator may use a lower-level mechanism again (e.g. variants of operators new
and delete
) to actually allocate and deallocate. If any of those steps elect to not release memory to the lower-level layer, there is potential impact on heap fragmentation.â Peter
Sep 25 at 10:34
Even if a string did "give back memory spontaneously", that is insufficient to avoid heap fragmentation. A string uses an allocator (by default, an object of type
std::allocator<char>
, but that can be changed) to allocate and deallocate memory, and the allocator may use a lower-level mechanism again (e.g. variants of operators new
and delete
) to actually allocate and deallocate. If any of those steps elect to not release memory to the lower-level layer, there is potential impact on heap fragmentation.â Peter
Sep 25 at 10:34
2
2
If you need to guarantee this behaviour, you can always used your own custom allocator
â doron
Sep 25 at 12:26
If you need to guarantee this behaviour, you can always used your own custom allocator
â doron
Sep 25 at 12:26
10
10
In my own experience, if I have to utter the phrase "I'm dependent on avoiding heap fragmentation," its a very good time to start considering identifying precise low level requirements, and potentially rolling your own allocation routines.
â Cort Ammon
Sep 25 at 18:06
In my own experience, if I have to utter the phrase "I'm dependent on avoiding heap fragmentation," its a very good time to start considering identifying precise low level requirements, and potentially rolling your own allocation routines.
â Cort Ammon
Sep 25 at 18:06
 |Â
show 2 more comments
4 Answers
4
active
oldest
votes
up vote
34
down vote
accepted
No guarantee whatsoever.
[string.cons]/36
defines assigning a const char*
to an std::string
in term of a move-assignment, whose definition is:
[string.cons]/32
basic_string& operator=(basic_string&& str) noexcept(/*...*/)
Effects: Move assigns as a sequence container, except that iterators, pointers and references may be invalidated.
This shows that the Committee let the implementation choose freely between an invalidating operation and a more conservative one. And to make things even clearer:
[basic.string]/4
References, pointers, and iterators referring to the elements of a
basic_ÃÂstring
sequence may be invalidated by the following uses of that basic_ÃÂstring object:
- (4.1) as an argument to any standard library function taking a reference to non-const
basic_ÃÂstring
as an argument.
- (4.2) Calling non-const member functions, except
operator
,at
,data
,front
,back
,begin
,rbegin
,end
, andrend
.
I ask because i'm depending on this to avoid heap fragmentation.
std::string
takes as template-parameter an allocator. If you're really concerned by a possible heap fragmentation, you could write your own, which with some heuristics could have an allocation strategy suited for your needs.
In practice, most implementations I know of would not reallocate memory in the case of your question. This can be checked by testing and/or checking your implementation doc and eventually source code.
4
You can imagine how undesirable such a guarantee would be (presuming it was given), if you had the Gettysburg Address stored in a string, and then replaced it with "Hello World."
â Cort Ammon
Sep 25 at 18:28
add a comment |Â
up vote
12
down vote
CPP reference states that assignment to a pointer-to-char
Replaces the contents with those of null-terminated character string pointed to by s as if by *this = basic_string(s), which involves a call to Traits::length(s).
This "as if" actually boils down to an rvalue assignment, so the following scenario is quite possible:
- A fresh temporary string is created.
This string steals its contents as via assignment to an rvalue reference.
3
cppreference is usually reliable, but the quoted statement implies that there is a guaranteed buffer replacement, which is bollocks. Other than that it's a good conceptual model. But it's just marginally simpler than the standard's description, quoted in YSC's answer, which would therefore be preferable.
â Cheers and hth. - Alf
Sep 25 at 10:34
5
@Cheersandhth.-Alf cppreference is paraphrasing the standard[string.cons]
â Caleth
Sep 25 at 10:39
4
@Cheersandhth.-Alf Does it really? It says "as if", which, in Standard, always means "with regard to observable side effects, aside from few those of constructions/destructions".
â bipll
Sep 25 at 10:46
@rustyx it's allowed to do either. You can conceptualise it as the temporary stealing the existing allocation, then returning it.
â Caleth
Sep 25 at 12:01
1
@rustyx The standard just talks about the effect. Given that the effect ofx = "hi";
is the same as the effect ofx.assign("hi");
, an implementation would do the efficient thing for both. libstdc++, for instance, has itsoperator=(const CharT*)
just directly callassign
â Barry
Sep 25 at 13:40
add a comment |Â
up vote
3
down vote
Is it guaranteed by the standard that std::string will not give back allocated memory spontaneously if reassigned from a string of a smaller size?
Regardless of the actual answer (which is "No, no guarantee") - you should employ the following principle: If it's not obvious that it has to be the case, then don't assume it is the case.
In your specific case - if you want tight control of heap behavior, you might not even want to use std::string
s at all (maybe; it depends). And you might not want to use the default allocator (again, maybe); and you might want to memoize strings; etc. What you should absolutely do is make fewer assumptions, measure if possible, and have explicit design to ensure your needs are met.
add a comment |Â
up vote
2
down vote
If your strings are short (up to 15 or 22 bytes, depending on the compiler/std lib) and you are using a relatively recent compiler in C++11 or later mode, then you are likely to benefit from the Short String Optimization (SSO). In this case the string contents are not separately allocated on the heap.
This link also contains a lot of details on common implementations and allocation strategies.
However, both of the strings in your example are too long for SSO.
Is it guaranteed by the standard? Is SSO guaranteed by the standard?
â pipe
Sep 26 at 0:40
@pipe No it isn't, what Paul implied in: "you are likely to benefit from the Short String Optimization (SSO)".
â YSC
Sep 26 at 7:17
@YSC Ok, but the question is rather specific, and OP already knows that it is likely to happen since he depends on it, so I don't understand what this actually answers.
â pipe
Sep 26 at 8:27
@pipe I agree this answer is slightly off, but it was answered right after OP asked their question. The question wasn't tagged language-lawyer at that time, and get edited after that. This is answering part of OP concern (mem frag) and provides an interesting insight. I've upvoted it for what it's worth.
â YSC
Sep 26 at 9:44
It's not meant to be a full answer, just a complement for the case of SSO. I think that the link is quite interesting regarding practical measures of std::string performance.
â Paul Floyd
Sep 26 at 10:52
add a comment |Â
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
34
down vote
accepted
No guarantee whatsoever.
[string.cons]/36
defines assigning a const char*
to an std::string
in term of a move-assignment, whose definition is:
[string.cons]/32
basic_string& operator=(basic_string&& str) noexcept(/*...*/)
Effects: Move assigns as a sequence container, except that iterators, pointers and references may be invalidated.
This shows that the Committee let the implementation choose freely between an invalidating operation and a more conservative one. And to make things even clearer:
[basic.string]/4
References, pointers, and iterators referring to the elements of a
basic_ÃÂstring
sequence may be invalidated by the following uses of that basic_ÃÂstring object:
- (4.1) as an argument to any standard library function taking a reference to non-const
basic_ÃÂstring
as an argument.
- (4.2) Calling non-const member functions, except
operator
,at
,data
,front
,back
,begin
,rbegin
,end
, andrend
.
I ask because i'm depending on this to avoid heap fragmentation.
std::string
takes as template-parameter an allocator. If you're really concerned by a possible heap fragmentation, you could write your own, which with some heuristics could have an allocation strategy suited for your needs.
In practice, most implementations I know of would not reallocate memory in the case of your question. This can be checked by testing and/or checking your implementation doc and eventually source code.
4
You can imagine how undesirable such a guarantee would be (presuming it was given), if you had the Gettysburg Address stored in a string, and then replaced it with "Hello World."
â Cort Ammon
Sep 25 at 18:28
add a comment |Â
up vote
34
down vote
accepted
No guarantee whatsoever.
[string.cons]/36
defines assigning a const char*
to an std::string
in term of a move-assignment, whose definition is:
[string.cons]/32
basic_string& operator=(basic_string&& str) noexcept(/*...*/)
Effects: Move assigns as a sequence container, except that iterators, pointers and references may be invalidated.
This shows that the Committee let the implementation choose freely between an invalidating operation and a more conservative one. And to make things even clearer:
[basic.string]/4
References, pointers, and iterators referring to the elements of a
basic_ÃÂstring
sequence may be invalidated by the following uses of that basic_ÃÂstring object:
- (4.1) as an argument to any standard library function taking a reference to non-const
basic_ÃÂstring
as an argument.
- (4.2) Calling non-const member functions, except
operator
,at
,data
,front
,back
,begin
,rbegin
,end
, andrend
.
I ask because i'm depending on this to avoid heap fragmentation.
std::string
takes as template-parameter an allocator. If you're really concerned by a possible heap fragmentation, you could write your own, which with some heuristics could have an allocation strategy suited for your needs.
In practice, most implementations I know of would not reallocate memory in the case of your question. This can be checked by testing and/or checking your implementation doc and eventually source code.
4
You can imagine how undesirable such a guarantee would be (presuming it was given), if you had the Gettysburg Address stored in a string, and then replaced it with "Hello World."
â Cort Ammon
Sep 25 at 18:28
add a comment |Â
up vote
34
down vote
accepted
up vote
34
down vote
accepted
No guarantee whatsoever.
[string.cons]/36
defines assigning a const char*
to an std::string
in term of a move-assignment, whose definition is:
[string.cons]/32
basic_string& operator=(basic_string&& str) noexcept(/*...*/)
Effects: Move assigns as a sequence container, except that iterators, pointers and references may be invalidated.
This shows that the Committee let the implementation choose freely between an invalidating operation and a more conservative one. And to make things even clearer:
[basic.string]/4
References, pointers, and iterators referring to the elements of a
basic_ÃÂstring
sequence may be invalidated by the following uses of that basic_ÃÂstring object:
- (4.1) as an argument to any standard library function taking a reference to non-const
basic_ÃÂstring
as an argument.
- (4.2) Calling non-const member functions, except
operator
,at
,data
,front
,back
,begin
,rbegin
,end
, andrend
.
I ask because i'm depending on this to avoid heap fragmentation.
std::string
takes as template-parameter an allocator. If you're really concerned by a possible heap fragmentation, you could write your own, which with some heuristics could have an allocation strategy suited for your needs.
In practice, most implementations I know of would not reallocate memory in the case of your question. This can be checked by testing and/or checking your implementation doc and eventually source code.
No guarantee whatsoever.
[string.cons]/36
defines assigning a const char*
to an std::string
in term of a move-assignment, whose definition is:
[string.cons]/32
basic_string& operator=(basic_string&& str) noexcept(/*...*/)
Effects: Move assigns as a sequence container, except that iterators, pointers and references may be invalidated.
This shows that the Committee let the implementation choose freely between an invalidating operation and a more conservative one. And to make things even clearer:
[basic.string]/4
References, pointers, and iterators referring to the elements of a
basic_ÃÂstring
sequence may be invalidated by the following uses of that basic_ÃÂstring object:
- (4.1) as an argument to any standard library function taking a reference to non-const
basic_ÃÂstring
as an argument.
- (4.2) Calling non-const member functions, except
operator
,at
,data
,front
,back
,begin
,rbegin
,end
, andrend
.
I ask because i'm depending on this to avoid heap fragmentation.
std::string
takes as template-parameter an allocator. If you're really concerned by a possible heap fragmentation, you could write your own, which with some heuristics could have an allocation strategy suited for your needs.
In practice, most implementations I know of would not reallocate memory in the case of your question. This can be checked by testing and/or checking your implementation doc and eventually source code.
edited Sep 28 at 11:23
answered Sep 25 at 10:18
YSC
18k34187
18k34187
4
You can imagine how undesirable such a guarantee would be (presuming it was given), if you had the Gettysburg Address stored in a string, and then replaced it with "Hello World."
â Cort Ammon
Sep 25 at 18:28
add a comment |Â
4
You can imagine how undesirable such a guarantee would be (presuming it was given), if you had the Gettysburg Address stored in a string, and then replaced it with "Hello World."
â Cort Ammon
Sep 25 at 18:28
4
4
You can imagine how undesirable such a guarantee would be (presuming it was given), if you had the Gettysburg Address stored in a string, and then replaced it with "Hello World."
â Cort Ammon
Sep 25 at 18:28
You can imagine how undesirable such a guarantee would be (presuming it was given), if you had the Gettysburg Address stored in a string, and then replaced it with "Hello World."
â Cort Ammon
Sep 25 at 18:28
add a comment |Â
up vote
12
down vote
CPP reference states that assignment to a pointer-to-char
Replaces the contents with those of null-terminated character string pointed to by s as if by *this = basic_string(s), which involves a call to Traits::length(s).
This "as if" actually boils down to an rvalue assignment, so the following scenario is quite possible:
- A fresh temporary string is created.
This string steals its contents as via assignment to an rvalue reference.
3
cppreference is usually reliable, but the quoted statement implies that there is a guaranteed buffer replacement, which is bollocks. Other than that it's a good conceptual model. But it's just marginally simpler than the standard's description, quoted in YSC's answer, which would therefore be preferable.
â Cheers and hth. - Alf
Sep 25 at 10:34
5
@Cheersandhth.-Alf cppreference is paraphrasing the standard[string.cons]
â Caleth
Sep 25 at 10:39
4
@Cheersandhth.-Alf Does it really? It says "as if", which, in Standard, always means "with regard to observable side effects, aside from few those of constructions/destructions".
â bipll
Sep 25 at 10:46
@rustyx it's allowed to do either. You can conceptualise it as the temporary stealing the existing allocation, then returning it.
â Caleth
Sep 25 at 12:01
1
@rustyx The standard just talks about the effect. Given that the effect ofx = "hi";
is the same as the effect ofx.assign("hi");
, an implementation would do the efficient thing for both. libstdc++, for instance, has itsoperator=(const CharT*)
just directly callassign
â Barry
Sep 25 at 13:40
add a comment |Â
up vote
12
down vote
CPP reference states that assignment to a pointer-to-char
Replaces the contents with those of null-terminated character string pointed to by s as if by *this = basic_string(s), which involves a call to Traits::length(s).
This "as if" actually boils down to an rvalue assignment, so the following scenario is quite possible:
- A fresh temporary string is created.
This string steals its contents as via assignment to an rvalue reference.
3
cppreference is usually reliable, but the quoted statement implies that there is a guaranteed buffer replacement, which is bollocks. Other than that it's a good conceptual model. But it's just marginally simpler than the standard's description, quoted in YSC's answer, which would therefore be preferable.
â Cheers and hth. - Alf
Sep 25 at 10:34
5
@Cheersandhth.-Alf cppreference is paraphrasing the standard[string.cons]
â Caleth
Sep 25 at 10:39
4
@Cheersandhth.-Alf Does it really? It says "as if", which, in Standard, always means "with regard to observable side effects, aside from few those of constructions/destructions".
â bipll
Sep 25 at 10:46
@rustyx it's allowed to do either. You can conceptualise it as the temporary stealing the existing allocation, then returning it.
â Caleth
Sep 25 at 12:01
1
@rustyx The standard just talks about the effect. Given that the effect ofx = "hi";
is the same as the effect ofx.assign("hi");
, an implementation would do the efficient thing for both. libstdc++, for instance, has itsoperator=(const CharT*)
just directly callassign
â Barry
Sep 25 at 13:40
add a comment |Â
up vote
12
down vote
up vote
12
down vote
CPP reference states that assignment to a pointer-to-char
Replaces the contents with those of null-terminated character string pointed to by s as if by *this = basic_string(s), which involves a call to Traits::length(s).
This "as if" actually boils down to an rvalue assignment, so the following scenario is quite possible:
- A fresh temporary string is created.
This string steals its contents as via assignment to an rvalue reference.
CPP reference states that assignment to a pointer-to-char
Replaces the contents with those of null-terminated character string pointed to by s as if by *this = basic_string(s), which involves a call to Traits::length(s).
This "as if" actually boils down to an rvalue assignment, so the following scenario is quite possible:
- A fresh temporary string is created.
This string steals its contents as via assignment to an rvalue reference.
edited Sep 25 at 13:12
answered Sep 25 at 10:19
bipll
7,3171824
7,3171824
3
cppreference is usually reliable, but the quoted statement implies that there is a guaranteed buffer replacement, which is bollocks. Other than that it's a good conceptual model. But it's just marginally simpler than the standard's description, quoted in YSC's answer, which would therefore be preferable.
â Cheers and hth. - Alf
Sep 25 at 10:34
5
@Cheersandhth.-Alf cppreference is paraphrasing the standard[string.cons]
â Caleth
Sep 25 at 10:39
4
@Cheersandhth.-Alf Does it really? It says "as if", which, in Standard, always means "with regard to observable side effects, aside from few those of constructions/destructions".
â bipll
Sep 25 at 10:46
@rustyx it's allowed to do either. You can conceptualise it as the temporary stealing the existing allocation, then returning it.
â Caleth
Sep 25 at 12:01
1
@rustyx The standard just talks about the effect. Given that the effect ofx = "hi";
is the same as the effect ofx.assign("hi");
, an implementation would do the efficient thing for both. libstdc++, for instance, has itsoperator=(const CharT*)
just directly callassign
â Barry
Sep 25 at 13:40
add a comment |Â
3
cppreference is usually reliable, but the quoted statement implies that there is a guaranteed buffer replacement, which is bollocks. Other than that it's a good conceptual model. But it's just marginally simpler than the standard's description, quoted in YSC's answer, which would therefore be preferable.
â Cheers and hth. - Alf
Sep 25 at 10:34
5
@Cheersandhth.-Alf cppreference is paraphrasing the standard[string.cons]
â Caleth
Sep 25 at 10:39
4
@Cheersandhth.-Alf Does it really? It says "as if", which, in Standard, always means "with regard to observable side effects, aside from few those of constructions/destructions".
â bipll
Sep 25 at 10:46
@rustyx it's allowed to do either. You can conceptualise it as the temporary stealing the existing allocation, then returning it.
â Caleth
Sep 25 at 12:01
1
@rustyx The standard just talks about the effect. Given that the effect ofx = "hi";
is the same as the effect ofx.assign("hi");
, an implementation would do the efficient thing for both. libstdc++, for instance, has itsoperator=(const CharT*)
just directly callassign
â Barry
Sep 25 at 13:40
3
3
cppreference is usually reliable, but the quoted statement implies that there is a guaranteed buffer replacement, which is bollocks. Other than that it's a good conceptual model. But it's just marginally simpler than the standard's description, quoted in YSC's answer, which would therefore be preferable.
â Cheers and hth. - Alf
Sep 25 at 10:34
cppreference is usually reliable, but the quoted statement implies that there is a guaranteed buffer replacement, which is bollocks. Other than that it's a good conceptual model. But it's just marginally simpler than the standard's description, quoted in YSC's answer, which would therefore be preferable.
â Cheers and hth. - Alf
Sep 25 at 10:34
5
5
@Cheersandhth.-Alf cppreference is paraphrasing the standard
[string.cons]
â Caleth
Sep 25 at 10:39
@Cheersandhth.-Alf cppreference is paraphrasing the standard
[string.cons]
â Caleth
Sep 25 at 10:39
4
4
@Cheersandhth.-Alf Does it really? It says "as if", which, in Standard, always means "with regard to observable side effects, aside from few those of constructions/destructions".
â bipll
Sep 25 at 10:46
@Cheersandhth.-Alf Does it really? It says "as if", which, in Standard, always means "with regard to observable side effects, aside from few those of constructions/destructions".
â bipll
Sep 25 at 10:46
@rustyx it's allowed to do either. You can conceptualise it as the temporary stealing the existing allocation, then returning it.
â Caleth
Sep 25 at 12:01
@rustyx it's allowed to do either. You can conceptualise it as the temporary stealing the existing allocation, then returning it.
â Caleth
Sep 25 at 12:01
1
1
@rustyx The standard just talks about the effect. Given that the effect of
x = "hi";
is the same as the effect of x.assign("hi");
, an implementation would do the efficient thing for both. libstdc++, for instance, has its operator=(const CharT*)
just directly call assign
â Barry
Sep 25 at 13:40
@rustyx The standard just talks about the effect. Given that the effect of
x = "hi";
is the same as the effect of x.assign("hi");
, an implementation would do the efficient thing for both. libstdc++, for instance, has its operator=(const CharT*)
just directly call assign
â Barry
Sep 25 at 13:40
add a comment |Â
up vote
3
down vote
Is it guaranteed by the standard that std::string will not give back allocated memory spontaneously if reassigned from a string of a smaller size?
Regardless of the actual answer (which is "No, no guarantee") - you should employ the following principle: If it's not obvious that it has to be the case, then don't assume it is the case.
In your specific case - if you want tight control of heap behavior, you might not even want to use std::string
s at all (maybe; it depends). And you might not want to use the default allocator (again, maybe); and you might want to memoize strings; etc. What you should absolutely do is make fewer assumptions, measure if possible, and have explicit design to ensure your needs are met.
add a comment |Â
up vote
3
down vote
Is it guaranteed by the standard that std::string will not give back allocated memory spontaneously if reassigned from a string of a smaller size?
Regardless of the actual answer (which is "No, no guarantee") - you should employ the following principle: If it's not obvious that it has to be the case, then don't assume it is the case.
In your specific case - if you want tight control of heap behavior, you might not even want to use std::string
s at all (maybe; it depends). And you might not want to use the default allocator (again, maybe); and you might want to memoize strings; etc. What you should absolutely do is make fewer assumptions, measure if possible, and have explicit design to ensure your needs are met.
add a comment |Â
up vote
3
down vote
up vote
3
down vote
Is it guaranteed by the standard that std::string will not give back allocated memory spontaneously if reassigned from a string of a smaller size?
Regardless of the actual answer (which is "No, no guarantee") - you should employ the following principle: If it's not obvious that it has to be the case, then don't assume it is the case.
In your specific case - if you want tight control of heap behavior, you might not even want to use std::string
s at all (maybe; it depends). And you might not want to use the default allocator (again, maybe); and you might want to memoize strings; etc. What you should absolutely do is make fewer assumptions, measure if possible, and have explicit design to ensure your needs are met.
Is it guaranteed by the standard that std::string will not give back allocated memory spontaneously if reassigned from a string of a smaller size?
Regardless of the actual answer (which is "No, no guarantee") - you should employ the following principle: If it's not obvious that it has to be the case, then don't assume it is the case.
In your specific case - if you want tight control of heap behavior, you might not even want to use std::string
s at all (maybe; it depends). And you might not want to use the default allocator (again, maybe); and you might want to memoize strings; etc. What you should absolutely do is make fewer assumptions, measure if possible, and have explicit design to ensure your needs are met.
edited Sep 26 at 11:35
answered Sep 25 at 21:29
einpoklum
30.7k24107219
30.7k24107219
add a comment |Â
add a comment |Â
up vote
2
down vote
If your strings are short (up to 15 or 22 bytes, depending on the compiler/std lib) and you are using a relatively recent compiler in C++11 or later mode, then you are likely to benefit from the Short String Optimization (SSO). In this case the string contents are not separately allocated on the heap.
This link also contains a lot of details on common implementations and allocation strategies.
However, both of the strings in your example are too long for SSO.
Is it guaranteed by the standard? Is SSO guaranteed by the standard?
â pipe
Sep 26 at 0:40
@pipe No it isn't, what Paul implied in: "you are likely to benefit from the Short String Optimization (SSO)".
â YSC
Sep 26 at 7:17
@YSC Ok, but the question is rather specific, and OP already knows that it is likely to happen since he depends on it, so I don't understand what this actually answers.
â pipe
Sep 26 at 8:27
@pipe I agree this answer is slightly off, but it was answered right after OP asked their question. The question wasn't tagged language-lawyer at that time, and get edited after that. This is answering part of OP concern (mem frag) and provides an interesting insight. I've upvoted it for what it's worth.
â YSC
Sep 26 at 9:44
It's not meant to be a full answer, just a complement for the case of SSO. I think that the link is quite interesting regarding practical measures of std::string performance.
â Paul Floyd
Sep 26 at 10:52
add a comment |Â
up vote
2
down vote
If your strings are short (up to 15 or 22 bytes, depending on the compiler/std lib) and you are using a relatively recent compiler in C++11 or later mode, then you are likely to benefit from the Short String Optimization (SSO). In this case the string contents are not separately allocated on the heap.
This link also contains a lot of details on common implementations and allocation strategies.
However, both of the strings in your example are too long for SSO.
Is it guaranteed by the standard? Is SSO guaranteed by the standard?
â pipe
Sep 26 at 0:40
@pipe No it isn't, what Paul implied in: "you are likely to benefit from the Short String Optimization (SSO)".
â YSC
Sep 26 at 7:17
@YSC Ok, but the question is rather specific, and OP already knows that it is likely to happen since he depends on it, so I don't understand what this actually answers.
â pipe
Sep 26 at 8:27
@pipe I agree this answer is slightly off, but it was answered right after OP asked their question. The question wasn't tagged language-lawyer at that time, and get edited after that. This is answering part of OP concern (mem frag) and provides an interesting insight. I've upvoted it for what it's worth.
â YSC
Sep 26 at 9:44
It's not meant to be a full answer, just a complement for the case of SSO. I think that the link is quite interesting regarding practical measures of std::string performance.
â Paul Floyd
Sep 26 at 10:52
add a comment |Â
up vote
2
down vote
up vote
2
down vote
If your strings are short (up to 15 or 22 bytes, depending on the compiler/std lib) and you are using a relatively recent compiler in C++11 or later mode, then you are likely to benefit from the Short String Optimization (SSO). In this case the string contents are not separately allocated on the heap.
This link also contains a lot of details on common implementations and allocation strategies.
However, both of the strings in your example are too long for SSO.
If your strings are short (up to 15 or 22 bytes, depending on the compiler/std lib) and you are using a relatively recent compiler in C++11 or later mode, then you are likely to benefit from the Short String Optimization (SSO). In this case the string contents are not separately allocated on the heap.
This link also contains a lot of details on common implementations and allocation strategies.
However, both of the strings in your example are too long for SSO.
answered Sep 25 at 10:43
Paul Floyd
2,54611729
2,54611729
Is it guaranteed by the standard? Is SSO guaranteed by the standard?
â pipe
Sep 26 at 0:40
@pipe No it isn't, what Paul implied in: "you are likely to benefit from the Short String Optimization (SSO)".
â YSC
Sep 26 at 7:17
@YSC Ok, but the question is rather specific, and OP already knows that it is likely to happen since he depends on it, so I don't understand what this actually answers.
â pipe
Sep 26 at 8:27
@pipe I agree this answer is slightly off, but it was answered right after OP asked their question. The question wasn't tagged language-lawyer at that time, and get edited after that. This is answering part of OP concern (mem frag) and provides an interesting insight. I've upvoted it for what it's worth.
â YSC
Sep 26 at 9:44
It's not meant to be a full answer, just a complement for the case of SSO. I think that the link is quite interesting regarding practical measures of std::string performance.
â Paul Floyd
Sep 26 at 10:52
add a comment |Â
Is it guaranteed by the standard? Is SSO guaranteed by the standard?
â pipe
Sep 26 at 0:40
@pipe No it isn't, what Paul implied in: "you are likely to benefit from the Short String Optimization (SSO)".
â YSC
Sep 26 at 7:17
@YSC Ok, but the question is rather specific, and OP already knows that it is likely to happen since he depends on it, so I don't understand what this actually answers.
â pipe
Sep 26 at 8:27
@pipe I agree this answer is slightly off, but it was answered right after OP asked their question. The question wasn't tagged language-lawyer at that time, and get edited after that. This is answering part of OP concern (mem frag) and provides an interesting insight. I've upvoted it for what it's worth.
â YSC
Sep 26 at 9:44
It's not meant to be a full answer, just a complement for the case of SSO. I think that the link is quite interesting regarding practical measures of std::string performance.
â Paul Floyd
Sep 26 at 10:52
Is it guaranteed by the standard? Is SSO guaranteed by the standard?
â pipe
Sep 26 at 0:40
Is it guaranteed by the standard? Is SSO guaranteed by the standard?
â pipe
Sep 26 at 0:40
@pipe No it isn't, what Paul implied in: "you are likely to benefit from the Short String Optimization (SSO)".
â YSC
Sep 26 at 7:17
@pipe No it isn't, what Paul implied in: "you are likely to benefit from the Short String Optimization (SSO)".
â YSC
Sep 26 at 7:17
@YSC Ok, but the question is rather specific, and OP already knows that it is likely to happen since he depends on it, so I don't understand what this actually answers.
â pipe
Sep 26 at 8:27
@YSC Ok, but the question is rather specific, and OP already knows that it is likely to happen since he depends on it, so I don't understand what this actually answers.
â pipe
Sep 26 at 8:27
@pipe I agree this answer is slightly off, but it was answered right after OP asked their question. The question wasn't tagged language-lawyer at that time, and get edited after that. This is answering part of OP concern (mem frag) and provides an interesting insight. I've upvoted it for what it's worth.
â YSC
Sep 26 at 9:44
@pipe I agree this answer is slightly off, but it was answered right after OP asked their question. The question wasn't tagged language-lawyer at that time, and get edited after that. This is answering part of OP concern (mem frag) and provides an interesting insight. I've upvoted it for what it's worth.
â YSC
Sep 26 at 9:44
It's not meant to be a full answer, just a complement for the case of SSO. I think that the link is quite interesting regarding practical measures of std::string performance.
â Paul Floyd
Sep 26 at 10:52
It's not meant to be a full answer, just a complement for the case of SSO. I think that the link is quite interesting regarding practical measures of std::string performance.
â Paul Floyd
Sep 26 at 10:52
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52495704%2fis-stdstring-guaranteed-not-to-give-back-memory-spontaneously%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
if the new string allocation is less than the previous allocation, no allocation occurs. If the new string requires more allocation than the current, a reallocation occurs. Similar to a std::vector.
â Samer Tufail
Sep 25 at 10:19
Strings reuse their buffers when assigned to shorter strings, so in your program there is only one allocation for the string. Unfortunately I can't find conveniently any citation from the standard on mobile
â Fureeish
Sep 25 at 10:20
1
Even if a string did "give back memory spontaneously", that is insufficient to avoid heap fragmentation. A string uses an allocator (by default, an object of type
std::allocator<char>
, but that can be changed) to allocate and deallocate memory, and the allocator may use a lower-level mechanism again (e.g. variants of operatorsnew
anddelete
) to actually allocate and deallocate. If any of those steps elect to not release memory to the lower-level layer, there is potential impact on heap fragmentation.â Peter
Sep 25 at 10:34
2
If you need to guarantee this behaviour, you can always used your own custom allocator
â doron
Sep 25 at 12:26
10
In my own experience, if I have to utter the phrase "I'm dependent on avoiding heap fragmentation," its a very good time to start considering identifying precise low level requirements, and potentially rolling your own allocation routines.
â Cort Ammon
Sep 25 at 18:06