I discovered that the sizeof(string)
is 28B for VC and 32B for GCC respectively(the data part allocated on the heap is not included). This makes me very skeptic about the efficiency of using string as a parameter of a c++ constructor. So I conducted a little experiment as below:
class Foo
{
static int inc;
int val;
int id;
public:
Foo(int value) :val(value), id(Foo::inc++) {
std::cout << to_string() << " being constructed\n";
}
~Foo() {
std::cout << to_string() << " being destroyed\n";
};
Foo(Foo const &other) :Foo(other.val) {
std::cout << other.to_string() << " being copied\n";
}
Foo& operator=(Foo const &other) {
val = other.val;
std::cout << other.to_string() << " being copied\n";
}
Foo(Foo &&other) :Foo(other.val) {
std::cout << other.to_string() << " being moved\n";
}
Foo& operator=(Foo &&other) {
val = other.val;
std::cout << other.to_string() << " being moved\n";
}
int value() const noexcept { return val; }
std::string to_string() const {
return std::string("Foo_") + std::to_string(id) + "_(" + std::to_string(val) + ")";
}
};
int Foo::inc = 0;
struct Bar {
Bar(Foo const &foo) :val(foo) {}
Bar(Foo &&foo) :val(std::move(foo)) {}
private:
Foo val;
};
//------- run it ------
Bar bar {42};
This is the result I got:
Foo_0_(42) being constructed
Foo_1_(42) being constructed
Foo_0_(42) being moved
Foo_0_(42) being destroyed
Foo_1_(42) being destroyed
Obviously, a temporary Foo instance was created on the spot of the argument of the ctor. So I suppose when I pass a const char*
to a constructor that expects a string, the same procedure would happen, i.d. a temp str >= 28/32 bytes would be created and dropped immediately after being moved/copied. That kind of cost just makes me uncomfortable. Don't get me wrong, I will use a string
as a data member of the class, it's only the formal argument type of the ctor that worries me.
Anyhow, if I replace the string
parameter with a const char*
, given that I can always resort to string::c_str()
, I assume I would never need to pay such a cost, would I? I'd like to hear your perspective. If there is anything wrong with my analysis, please just point it out. If there is some mechanism which can eliminate the cost of the temp string, please teach me how would it work. If the temp string is inevitable, do I have to overload the ctor with both const char*
and string&&
, one to avoid temp string and one for rvalue string to avoid deep-copy? Thanks in advance!