Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7988449
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 4, 20262026-06-04T12:27:24+00:00 2026-06-04T12:27:24+00:00

I was at a lecture with Bjarne Stoustrup recently, he was talking about c++

  • 0

I was at a lecture with Bjarne Stoustrup recently, he was talking about c++ 11 and why it made sense.

One of his examples of new awesomeness was the news ‘&&’ symbol for move constructors.

Then I want home and started thinking, “When would I ever need such a thing?”.

My first example was the code below:

class Number {
private:
    int value;
public:
    Number(const int value) : value(value){
        cout << "Build Constructor on " << value << endl;
    }
    Number(const Number& orig) : value(orig.value){
        cout << "Copy Constructor on " << value << endl;        
    }
    virtual ~Number(){}

    int toInt() const{
        return value;
    }


    friend const Number operator+(const Number& n0, const Number& n1); 
};

const Number operator+(const Number& n0, const Number& n1){
    return  Number(n0.value + n1.value);
}

int main(int argc, char** argv) {

    const Number n3 = (Number(2) + Number(1));
    cout << n3.toInt() << endl;
    return 0;
}

This code does exactly what the move constructor is supposed to solve. The n3 variable is constructed from a reference to the value returned from the ‘+’ operator.

Except this is the output from running the code:

Build Constructor on 1
Build Constructor on 2
Build Constructor on 3
3

RUN SUCCESSFUL 

What the output shows is that the copy constructor never gets called — and this is with optimizations turned off. I’m having a hard time twisting the arm of the code enough to make it run the copy construtor. wrapping the result in a std::pair did the trick, but it kept me thinking.

Is the argument of move-constructors in operator arithmetic’s actually a failed argument?

Why is’nt my copy constructor called and why is it called in :

using namespace std;

class Number {
private:
    int value;
public:
    Number(const int value) : value(value){
        cout << "Build Constructor on " << value << endl;
    }
    Number(const Number& orig) : value(orig.value){
        cout << "Copy Constructor on " << value << endl;        
    }
    virtual ~Number(){}

    int toInt() const{
        return value;
    }


    friend const std::pair<const Number, const Number> operator+(const Number& n0, const Number& n1); 
};

const std::pair<const Number, const Number> operator+(const Number& n0, const Number& n1){
    return  make_pair(Number(n0.value + n1.value), n0);
}

int main(int argc, char** argv) {

    const Number n3 = (Number(2) + Number(1)).first;
    cout << n3.toInt() << endl;
    return 0;
}

With output:

Build Constructor on 1
Build Constructor on 2
Copy Constructor on 2
Build Constructor on 3
Copy Constructor on 3
Copy Constructor on 2
Copy Constructor on 3
Copy Constructor on 2
Copy Constructor on 3
3

RUN SUCCESSFUL 

I would like to know what the logic is and why the pair operator basically screws up the performance?

update:

I did another modification and found that if I replaced make_pair with the actual templated constructor of the pair pair<const Number, const Number> this reduced the number of times the copy constructor got fired:

class Number {
private:
    int value;
public:
    Number(const int value) : value(value){
        cout << "Build Constructor on " << value << endl;
    }
    Number(const Number& orig) : value(orig.value){
        cout << "Copy Constructor on " << value << endl;        
    }
    virtual ~Number(){}

    int toInt() const{
        return value;
    }


    friend const std::pair<const Number, const Number> operator+(const Number& n0, const Number& n1); 
};



const std::pair<const Number, const Number> operator+(const Number& n0, const Number& n1){
    return  std::pair<const Number, const Number>(Number(n0.value + n1.value), n0);
}

int main(int argc, char** argv) {

    const Number n3 = (Number(2) + Number(1)).first;
    cout << n3.toInt() << endl;
    return 0;
}

output :

Build Constructor on 1
Build Constructor on 2
Build Constructor on 3
Copy Constructor on 3
Copy Constructor on 2
Copy Constructor on 3
3

RUN SUCCESSFUL

So it would apear using make_pair is harmfull?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-04T12:27:26+00:00Added an answer on June 4, 2026 at 12:27 pm

    Consider this simple C++ code:

    class StringHolder
    {
      std::string member;
    public:
    
      StringHolder(const std::string &newMember) : member(newMember) {}
    };
    
    std::string value = "I am a string that will probably be heap-allocated.";
    StringHolder hold(value);
    

    After executing the second line, how many copies of the string exist? The answer is two: one stored in value, and one stored in hold. That is fine… sometimes. There will often be times when you want to give someone a copy of a string while keeping it for yourself. But there are times you don’t want to do that too. For example:

    StringHolder hold("I am a string that will probably be heap-allocated.");
    

    This will create a std::string temporary, which will then be passed to StringHolder‘s constructor. The constructor will copy-construct its member. After the constructor completes, the temporary will be destroyed. At one point, we had two copies of the string, for no reason whatsoever.

    There was no point of having two copies of the string. What we wanted to do was move the std::string parameter into the StringHolder, so that there’s only ever one copy of the string.

    That’s where move construction comes in.

    A std::string is basically just a wrapper around a pointer to an allocated array of characters, and a size containing the length of that array (and a capacity, but nevermind that now). If you have a std::string, and you want to move it into the other, then the new string must claim ownership of that allocated array of characters, and the old string must relinquish ownership. In C++03, you could do that with a swap operation:

    std::string oldStr = "I am a string that will probably be heap-allocated.";
    std::string newStr;
    std::swap(newStr, oldStr);
    

    This moves the contents of oldStr into newStr without any memory allocation.

    C++11’s move syntax provides two important features that std::swap does not.

    First, move can happen implicitly (but only when it’s safe to do so). You must explicitly call swap if you want swapping; moving can happen by writing natural code. For example, take our StringHolder from before and make one change:

    class StringHolder
    {
      std::string member;
    public:
    
      StringHolder(std::string newMember) : member(std::move(newMember)) {}
    };
    
    StringHolder hold("I am a string that will probably be heap-allocated.");
    

    How many copies of this string are ever created? The answer is… just one: the construction of the temporary. Because it is a temporary, C++11 is smart enough to know that it can move-construct anything being initialized by it. So it move-constructs the value parameter of the StringHolder constructor (or more likely elides the construction altogether). This moves the stored memory from the temporary into newMember. So no copying takes place.

    After that, we invoke the move constructor explicitly when we construct member. This again moves the allocated memory from newMember to member.

    We only ever allocate a string once. That can be a big savings in performance.

    Now, how does this relate to constructors of your own types? Well, consider this code:

    class StringHolder
    {
      std::string member;
    public:
    
      StringHolder(std::string newMember) : member(std::move(newMember)) {}
    
      StringHolder(const StringHolder &old) : member(old.member) {}
      StringHolder(StringHolder &&old) : member(std::move(old.member)) {}
    };
    
    StringHolder oldHold = std::string("I am a string that will probably be heap-allocated.");
    StringHolder newHold(oldHold);
    

    This time, we now have a class with a copy and move constructor. How many copies of the string do we get?

    Two. Of course it’s two. We have oldHold and newHold, each with a copy of the string.

    But, if we did this:

    StringHolder oldHold = std::string("I am a string that will probably be heap-allocated.");
    StringHolder newHold(std::move(oldHold));
    

    Then there would again only ever be one copy of the string lying around.

    That’s why movement is important. That’s why it matters: it reduces the number of copies of things you may need to have lying around.


    Why is’nt my copy constructor called

    Your copy constructor wasn’t called because it was elided. It’s doing return-value optimization. Turning off optimization isn’t going to help, because most compilers will elide anyway. There is no reason not to when elision is possible.

    For function return values, movement is important in cases where elision is not possible.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

In a lecture about JIT in Hotspot I want to give as many examples
Recently I attended a lecture concerning some design patterns: The following code had been
Some time ago (~4-5months ago) I attented a lecture about Java EE and at
I was recently watching a google lecture on mysql and learnt that MySQL wont
The question posed came about during a 2nd Year Comp Science lecture while discussing
One of my lecture slides gives an example of arithmetic overflow and carry in
in the Turing lecture 2010 Christopher Bishop talks about machine learning undergoing a revolution
I watched the Stanford online video lecture about java programming by Mehran Sami. In
during a lecture my professor gave examples of several actions involving databases and the
I am about to begin coding a demo program for a lecture I'm about

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.