why would std::equal_to cause dynamic allocation?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
6
down vote

favorite
1












Consider the following simple example, where I am using std::equal_to to compare two std::pair<std::string, unsigned>. The operator new is overloaded so that it prints a message when allocations take place (live code here):



#include <functional>
#include <string>
#include <iostream>

// overloaded to see when heap allocations take place
void* operator new(std::size_t n)

std::cout << "Allocating " << n << std::endl;
return malloc(n);


int main()

using key_type = std::pair<std::string, unsigned>;
auto key1 = std::make_pair(std::string("a_______long______string______"), 1);
auto key2 = std::make_pair(std::string("a_______long______string______"), 1);

std::cout << "Finished initial allocationsnn" << std::endl;

std::equal_to<key_type> eq;
eq(key1, key2); // how can this cause dynamic allocation???



The message I am seeing is



Allocating 31
Allocating 31
Finished initial allocations


Allocating 31
Allocating 31


You can see there are two allocations taking place when comparing key1 and key2. But why? std::equal_to's operator takes its arguments by const reference so no allocation should take place... what I am missing? Thanks.










share|improve this question























  • Build flags/compiler command line?
    – Yakk - Adam Nevraumont
    35 mins ago










  • @Yakk-AdamNevraumont gcc 8.2.0 using c++17 with O2 optimisation
    – linuxfever
    32 mins ago















up vote
6
down vote

favorite
1












Consider the following simple example, where I am using std::equal_to to compare two std::pair<std::string, unsigned>. The operator new is overloaded so that it prints a message when allocations take place (live code here):



#include <functional>
#include <string>
#include <iostream>

// overloaded to see when heap allocations take place
void* operator new(std::size_t n)

std::cout << "Allocating " << n << std::endl;
return malloc(n);


int main()

using key_type = std::pair<std::string, unsigned>;
auto key1 = std::make_pair(std::string("a_______long______string______"), 1);
auto key2 = std::make_pair(std::string("a_______long______string______"), 1);

std::cout << "Finished initial allocationsnn" << std::endl;

std::equal_to<key_type> eq;
eq(key1, key2); // how can this cause dynamic allocation???



The message I am seeing is



Allocating 31
Allocating 31
Finished initial allocations


Allocating 31
Allocating 31


You can see there are two allocations taking place when comparing key1 and key2. But why? std::equal_to's operator takes its arguments by const reference so no allocation should take place... what I am missing? Thanks.










share|improve this question























  • Build flags/compiler command line?
    – Yakk - Adam Nevraumont
    35 mins ago










  • @Yakk-AdamNevraumont gcc 8.2.0 using c++17 with O2 optimisation
    – linuxfever
    32 mins ago













up vote
6
down vote

favorite
1









up vote
6
down vote

favorite
1






1





Consider the following simple example, where I am using std::equal_to to compare two std::pair<std::string, unsigned>. The operator new is overloaded so that it prints a message when allocations take place (live code here):



#include <functional>
#include <string>
#include <iostream>

// overloaded to see when heap allocations take place
void* operator new(std::size_t n)

std::cout << "Allocating " << n << std::endl;
return malloc(n);


int main()

using key_type = std::pair<std::string, unsigned>;
auto key1 = std::make_pair(std::string("a_______long______string______"), 1);
auto key2 = std::make_pair(std::string("a_______long______string______"), 1);

std::cout << "Finished initial allocationsnn" << std::endl;

std::equal_to<key_type> eq;
eq(key1, key2); // how can this cause dynamic allocation???



The message I am seeing is



Allocating 31
Allocating 31
Finished initial allocations


Allocating 31
Allocating 31


You can see there are two allocations taking place when comparing key1 and key2. But why? std::equal_to's operator takes its arguments by const reference so no allocation should take place... what I am missing? Thanks.










share|improve this question















Consider the following simple example, where I am using std::equal_to to compare two std::pair<std::string, unsigned>. The operator new is overloaded so that it prints a message when allocations take place (live code here):



#include <functional>
#include <string>
#include <iostream>

// overloaded to see when heap allocations take place
void* operator new(std::size_t n)

std::cout << "Allocating " << n << std::endl;
return malloc(n);


int main()

using key_type = std::pair<std::string, unsigned>;
auto key1 = std::make_pair(std::string("a_______long______string______"), 1);
auto key2 = std::make_pair(std::string("a_______long______string______"), 1);

std::cout << "Finished initial allocationsnn" << std::endl;

std::equal_to<key_type> eq;
eq(key1, key2); // how can this cause dynamic allocation???



The message I am seeing is



Allocating 31
Allocating 31
Finished initial allocations


Allocating 31
Allocating 31


You can see there are two allocations taking place when comparing key1 and key2. But why? std::equal_to's operator takes its arguments by const reference so no allocation should take place... what I am missing? Thanks.







c++ heap-memory std-pair






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 30 mins ago









juanchopanza

185k21294402




185k21294402










asked 42 mins ago









linuxfever

1,6481921




1,6481921











  • Build flags/compiler command line?
    – Yakk - Adam Nevraumont
    35 mins ago










  • @Yakk-AdamNevraumont gcc 8.2.0 using c++17 with O2 optimisation
    – linuxfever
    32 mins ago

















  • Build flags/compiler command line?
    – Yakk - Adam Nevraumont
    35 mins ago










  • @Yakk-AdamNevraumont gcc 8.2.0 using c++17 with O2 optimisation
    – linuxfever
    32 mins ago
















Build flags/compiler command line?
– Yakk - Adam Nevraumont
35 mins ago




Build flags/compiler command line?
– Yakk - Adam Nevraumont
35 mins ago












@Yakk-AdamNevraumont gcc 8.2.0 using c++17 with O2 optimisation
– linuxfever
32 mins ago





@Yakk-AdamNevraumont gcc 8.2.0 using c++17 with O2 optimisation
– linuxfever
32 mins ago













1 Answer
1






active

oldest

votes

















up vote
7
down vote



accepted










It is because you make copies of the pairs.



The types of keyX are std::pair<std::string, int>. eq has has a function call operator for the arguments const std::pair<std::string, unsigned>&, const std::pair<std::string, unsigned>&. As the types do not match, the references cannot be bound to the arguments directly. However, int is implicitly convertible to unsigned and so given pair is implicitly convertible to the argument pair.



So, you implicitly create a pair of temporary arguments for the comparison. The creation of the temporary strings cause the memory allocation.




If you had used std::equal_to<> as the comparison operator, it would have not created copies as it deduces the argument types, and thus wouldn't have caused the conversion.






share|improve this answer






















  • Arghhhh! How did I miss that? Thanks for spotting!
    – linuxfever
    29 mins ago










Your Answer





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

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

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

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
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%2f52919315%2fwhy-would-stdequal-to-cause-dynamic-allocation%23new-answer', 'question_page');

);

Post as a guest






























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
7
down vote



accepted










It is because you make copies of the pairs.



The types of keyX are std::pair<std::string, int>. eq has has a function call operator for the arguments const std::pair<std::string, unsigned>&, const std::pair<std::string, unsigned>&. As the types do not match, the references cannot be bound to the arguments directly. However, int is implicitly convertible to unsigned and so given pair is implicitly convertible to the argument pair.



So, you implicitly create a pair of temporary arguments for the comparison. The creation of the temporary strings cause the memory allocation.




If you had used std::equal_to<> as the comparison operator, it would have not created copies as it deduces the argument types, and thus wouldn't have caused the conversion.






share|improve this answer






















  • Arghhhh! How did I miss that? Thanks for spotting!
    – linuxfever
    29 mins ago














up vote
7
down vote



accepted










It is because you make copies of the pairs.



The types of keyX are std::pair<std::string, int>. eq has has a function call operator for the arguments const std::pair<std::string, unsigned>&, const std::pair<std::string, unsigned>&. As the types do not match, the references cannot be bound to the arguments directly. However, int is implicitly convertible to unsigned and so given pair is implicitly convertible to the argument pair.



So, you implicitly create a pair of temporary arguments for the comparison. The creation of the temporary strings cause the memory allocation.




If you had used std::equal_to<> as the comparison operator, it would have not created copies as it deduces the argument types, and thus wouldn't have caused the conversion.






share|improve this answer






















  • Arghhhh! How did I miss that? Thanks for spotting!
    – linuxfever
    29 mins ago












up vote
7
down vote



accepted







up vote
7
down vote



accepted






It is because you make copies of the pairs.



The types of keyX are std::pair<std::string, int>. eq has has a function call operator for the arguments const std::pair<std::string, unsigned>&, const std::pair<std::string, unsigned>&. As the types do not match, the references cannot be bound to the arguments directly. However, int is implicitly convertible to unsigned and so given pair is implicitly convertible to the argument pair.



So, you implicitly create a pair of temporary arguments for the comparison. The creation of the temporary strings cause the memory allocation.




If you had used std::equal_to<> as the comparison operator, it would have not created copies as it deduces the argument types, and thus wouldn't have caused the conversion.






share|improve this answer














It is because you make copies of the pairs.



The types of keyX are std::pair<std::string, int>. eq has has a function call operator for the arguments const std::pair<std::string, unsigned>&, const std::pair<std::string, unsigned>&. As the types do not match, the references cannot be bound to the arguments directly. However, int is implicitly convertible to unsigned and so given pair is implicitly convertible to the argument pair.



So, you implicitly create a pair of temporary arguments for the comparison. The creation of the temporary strings cause the memory allocation.




If you had used std::equal_to<> as the comparison operator, it would have not created copies as it deduces the argument types, and thus wouldn't have caused the conversion.







share|improve this answer














share|improve this answer



share|improve this answer








edited 24 mins ago

























answered 30 mins ago









user2079303

72k550109




72k550109











  • Arghhhh! How did I miss that? Thanks for spotting!
    – linuxfever
    29 mins ago
















  • Arghhhh! How did I miss that? Thanks for spotting!
    – linuxfever
    29 mins ago















Arghhhh! How did I miss that? Thanks for spotting!
– linuxfever
29 mins ago




Arghhhh! How did I miss that? Thanks for spotting!
– linuxfever
29 mins ago

















 

draft saved


draft discarded















































 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52919315%2fwhy-would-stdequal-to-cause-dynamic-allocation%23new-answer', 'question_page');

);

Post as a guest













































































Comments

Popular posts from this blog

Long meetings (6-7 hours a day): Being “babysat” by supervisor

Is the Concept of Multiple Fantasy Races Scientifically Flawed? [closed]

Confectionery