Reputation: 2549
Let's say I have a rather large class A
where there is a member of another class B
:
class A {
various large data members here
}
class B {
public:
setA( .... );
private:
A a;
}
What's the best (both in terms of speed but also code cleanliness) to write the setter for the A
member in B
?
First option would be typical C++98 style:
void setA(const A& a) { this.a = a; }
and using it like
B b;
A a;
b.setA(a);
This needs at least one copy, which could be costly. More efficient for large objects would probably a pointer:
class B {
public:
setA( .... );
private:
A *a;
}
setA(A *a) { this->a = a; }
and
B b;
A *a = new A();
b.setA(a);
This comes with all the nastiness of pointers, having to write custom destructors etc. In C++14 one could use std::uniuqe_ptr, but still this is way less cleaner than simply having a non-pointer member of A
in B
.
In C++14 there might be the option of using rvalues
and move semantics with simple call by value, i.e.
void setA(A a) { this.a = std::move(a); }
and calling it like this:
B b;
A a;
b.setA(std::move(a)); // if we don't need a anymore
This is nice and clean and should be fast, but:
A
to be copied).Herb Sutter arguments in his slides on Back to the Basics! Essentials of Modern C++ Style that you should usually prefer
void setA(const A& a) { this.a = a; }
but he talks in his presentation about a rather small member (a string), so for larger, more complex objects, this might not apply...
What is the proper way of doing it (In Java, this so easy...)
Upvotes: 0
Views: 182
Reputation: 976
You can have two setters, one for rvalue refferences, the other for const&, like this:
void setA(const A& a) { a_ = a; }
void setA(A&& a) { a_ = std::move(a); }
Or, if you don't intend to use setA with any other types you could use universal refference:
template<typename T>
void setA(T&& a_) { a_ = std::forward<T>(a); }
But since you already allow setting the value, you might as well consider making it public, so that you don't have to worry at all about the setters.
Upvotes: 1
Reputation: 606
Your object should be ready to use after construction. Why don't pass class A during the construction of class B?
#include <memory>
class A
{
public:
A(int a) : a{ a } {}
private:
int a;
};
class B
{
public:
B(int b, A a) : b{ b }, a{ std::make_unique<A>(a) } {}
private:
int b;
std::unique_ptr<A> a;
};
int main()
{
B b(int{ 4 }, A{ 1 });
}
Upvotes: 1