Question about object copy


#1

Hi,
I want to understand the cost of copying object in chaiscript, so I make this simple program:

using namespace std;
using namespace chaiscript;

struct Test
{
    Test()
    {
        cout << "Def Const\n";
    }

    Test(const Test& t)
    {
        cout << "Copy Const\n";
    }
    ~Test()
    {
        cout << "Dest\n";
    }
};

Test Create()
{
    return Test();
}

int main(void)
{
    chaiscript::ChaiScript chai;
    chai.add(user_type<Test>(), "Test");
    chai.add(bootstrap::basic_constructors<Test>("Test"));
    chai.add(fun(Create), "create");
    chai.eval("create()");
}

The output is :

Def Const
Copy Const
Dest 
Copy Const
Copy Const
Dest
Dest
Dest

Why there are so many copy constructor called ?


#2

I’m in the process at looking at issues related to that, but the thing to understand is that the object you create has to be boxed up for use inside of ChaiScript, in a Boxed_Value object.

A few things:

  1. Can you verify what version of ChaiScript you are using? I see “only” 2 copy constructions happening when I execute this code.
  2. Because the value has to be boxed up, supplying a move constructor can help a lot.

See this code:

#include <iostream>
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/dispatchkit/bootstrap.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>

struct Test
{

  Test()
  {
    std::cout << "Def Const\n";
  }

  Test(const Test& t)
  {
    std::cout << "Copy Const\n";
  }
  Test(Test &&)
  {
    std::cout << "Move constructed\n";
  }

  ~Test()
  {
    std::cout << "Dest\n";
  }
};

Test Create()
{
  return Test();
}

int main()
{
  chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
  chai.add(chaiscript::user_type<Test>(), "Test");
  chai.add(chaiscript::bootstrap::basic_constructors<Test>("Test"));
  chai.add(chaiscript::fun(Create), "create");
  chai.eval("create()");
}

Which gives me:

Def Const
Move constructed
Move constructed
Dest
Dest
Dest

This not ideal, but much better. I’ll be sure to put your example on my to-do list. It might explain some of the performance related issues I’ve been looking at lately. But make sure you provide a move constructor or do:

Test(Test &&) = default;

Because you provided a custom destructor in your code, you prevented the compiler from generating a move constructor for you.

-Jason


#3

I’m using version 5.7.0 with Visual C++ 2013 in Windows 7. When I used your code the output is :

Def Const
Move constructed
Dest
Move constructed
Move constructed
Dest
Dest
Dest

#4

Can you check the current develop branch:


https://github.com/ChaiScript/ChaiScript/archive/develop.zip

It should result in exactly one construction and one move construction.

-Jaosn


#5

I download the code from [https://github.com/ChaiScript/ChaiScript/archive/develop.zip][1]
and the result is this:

Def Const
Move constructed
Dest
Move constructed
Dest
Dest

Maybe the extra copy is from the return value of eval ?
[1]: https://github.com/ChaiScript/ChaiScript/archive/develop.zip


#6

I think I’m going to have to try it on MSVC, there must be something else going on there.


#7

I’ve added an issue here you can follow along with: https://github.com/ChaiScript/ChaiScript/issues/165


#8

Ok, the best we can get it down to is 2 moves on MSVC. The compiler won’t let me get it better than that, at least using the same techniques that get me down to 1 move on GCC/Clang.

I’ve closed the issue, since it’s the best I can get it to