Вместо этих двух подходов
Person(const string& firstName, const string& lastName);
и
Person(string firstName, string lastName);
более эффективный подход - это когда у вас есть вместе следующие два конструктора
Person(const string &firstName, const string &lastName);
Person( string &&firstName, string &&lastName );
Это Подход
Person(const string& firstName, const string& lastName);
менее эффективен, когда аргументы являются r-значениями.
Этот подход
Person(string firstName, string lastName);
менее эффективен, когда аргументы имеют l-значения.
Вот две демонстрационные программы, которые показывают различия между тремя подходами.
#include <iostream>
struct A
{
static int value;
explicit A() : x( ++value )
{
std::cout << "explicit A(), x = " << x << "\n";
}
A( const A &a ) noexcept : x( ++value )
{
std::cout << "A( const A & ), x = " << x << "\n";
}
A( A &&a ) noexcept : x( ++value )
{
std::cout << "A( A && ), x = " << x << "\n";
}
~A()
{
std::cout << "~A(), x = " << x << "\n";
}
int x;
};
int A::value = 0;
struct B
{
B( const A &a1, const A &a2 ) : a1( a1 ), a2( a2 )
{
std::cout << "B( const A &, const A & )\n";
}
A a1, a2;
};
struct C
{
C( A a1, A a2 ) : a1( std::move( a1 ) ), a2( std::move( a2 ) )
{
std::cout << "C( A, A )\n";
}
A a1, a2;
};
struct D
{
D( const A &a1, const A &a2 ) : a1( a1 ), a2( a2 )
{
std::cout << "D( const A &, const A & )\n";
}
D( A &&a1, A &&a2 ) : a1( std::move( a1 ) ), a2( std::move( a2 ) )
{
std::cout << "D( A &&, A && )\n";
}
A a1, a2;
};
int main()
{
A a1;
A a2;
std::cout << '\n';
B b( a1, a2 );
std::cout << "b.a1.x = " << b.a1.x << ", b.a2.x = " << b.a2.x << '\n';
std::cout << '\n';
C c( a1, a2 );
std::cout << "c.a1.x = " << c.a1.x << ", c.a2.x = " << c.a2.x << '\n';
std::cout << '\n';
D d( a1, a2 );
std::cout << "d.a1.x = " << d.a1.x << ", d.a2.x = " << d.a2.x << '\n';
std::cout << '\n';
return 0;
}
Вывод программы:
explicit A(), x = 1
explicit A(), x = 2
A( const A & ), x = 3
A( const A & ), x = 4
B( const A &, const A & )
b.a1.x = 3, b.a2.x = 4
A( const A & ), x = 5
A( const A & ), x = 6
A( A && ), x = 7
A( A && ), x = 8
C( A, A )
~A(), x = 6
~A(), x = 5
c.a1.x = 7, c.a2.x = 8
A( const A & ), x = 9
A( const A & ), x = 10
D( const A &, const A & )
d.a1.x = 9, d.a2.x = 10
~A(), x = 10
~A(), x = 9
~A(), x = 8
~A(), x = 7
~A(), x = 4
~A(), x = 3
~A(), x = 2
~A(), x = 1
И
#include <iostream>
struct A
{
static int value;
explicit A() : x( ++value )
{
std::cout << "explicit A(), x = " << x << "\n";
}
A( const A &a ) noexcept : x( ++value )
{
std::cout << "A( const A & ), x = " << x << "\n";
}
A( A &&a ) noexcept : x( ++value )
{
std::cout << "A( A && ), x = " << x << "\n";
}
~A()
{
std::cout << "~A(), x = " << x << "\n";
}
int x;
};
int A::value = 0;
struct B
{
B( const A &a1, const A &a2 ) : a1( a1 ), a2( a2 )
{
std::cout << "B( const A &, const A & )\n";
}
A a1, a2;
};
struct C
{
C( A a1, A a2 ) : a1( std::move( a1 ) ), a2( std::move( a2 ) )
{
std::cout << "C( A, A )\n";
}
A a1, a2;
};
struct D
{
D( const A &a1, const A &a2 ) : a1( a1 ), a2( a2 )
{
std::cout << "D( const A &, const A & )\n";
}
D( A &&a1, A &&a2 ) : a1( std::move( a1 ) ), a2( std::move( a2 ) )
{
std::cout << "D( A &&, A && )\n";
}
A a1, a2;
};
int main()
{
B b( A{}, A{} );
std::cout << "b.a1.x = " << b.a1.x << ", b.a2.x = " << b.a2.x << '\n';
std::cout << '\n';
C c( A{}, A{} );
std::cout << "c.a1.x = " << c.a1.x << ", c.a2.x = " << c.a2.x << '\n';
std::cout << '\n';
D d( A{}, A{} );
std::cout << "d.a1.x = " << d.a1.x << ", d.a2.x = " << d.a2.x << '\n';
std::cout << '\n';
return 0;
}
Вывод программы:
explicit A(), x = 1
explicit A(), x = 2
A( const A & ), x = 3
A( const A & ), x = 4
B( const A &, const A & )
~A(), x = 2
~A(), x = 1
b.a1.x = 3, b.a2.x = 4
explicit A(), x = 5
explicit A(), x = 6
A( A && ), x = 7
A( A && ), x = 8
C( A, A )
~A(), x = 6
~A(), x = 5
c.a1.x = 7, c.a2.x = 8
explicit A(), x = 9
explicit A(), x = 10
A( A && ), x = 11
A( A && ), x = 12
D( A &&, A && )
~A(), x = 10
~A(), x = 9
d.a1.x = 11, d.a2.x = 12
~A(), x = 12
~A(), x = 11
~A(), x = 8
~A(), x = 7
~A(), x = 4
~A(), x = 3
Видно, что в обеих программах класс D
ведет себя более эффективно по сравнению с классами B
и C
.