I have the following class (stripped down to contain only the relevant parts):
#include <string>
class Text
{
private:
std::string _text;
public:
Text(std::string&& text) :
_text(std::move(text))
{
}
operator const std::string&() const
{
return _text;
}
};
My question is: if I want to obtain a const std::string&
, can I do it like this without any penalty:
Text text("fred");
auto& s = static_cast<std::string>(text);
Or will this construct an intermediate std::string
that I end up getting a reference to? Is there a standard approach to this kind of scenario? I am reasonably new to C++.
The static_cast operator converts variable j to type float . This allows the compiler to generate a division with an answer of type float . All static_cast operators resolve at compile time and do not remove any const or volatile modifiers.
As we learnt in the generic types example, static_cast<> will fail if you try to cast an object to another unrelated class, while reinterpret_cast<> will always succeed by "cheating" the compiler to believe that the object is really that unrelated class.
The static_cast operator converts a given expression to a specified type.
If, in your code, you know you do not need a result somewhere, you can use the static_cast<void> method to mark the result as discarded – but the compiler will consider the variable used then and no longer create a warning or error.
No, when you're calling static_cast<std::string>(text)
, you're calling the implicitly defined copy constructor and creating a temporary object.
However, if you would be calling
auto& s = static_cast<const std::string&>(text);
,then you would correctly be calling the explicit conversion operator operator const Noisy&()
.
struct Noisy {
Noisy() { std::cout << "Default construct" << std::endl; }
Noisy(const Noisy&) { std::cout << "Copy construct" << std::endl; }
Noisy(Noisy&&) { std::cout << "Move construct" << std::endl; }
Noisy& operator=(const Noisy&) { std::cout << "C-assign" << std::endl; return *this; }
Noisy& operator=(Noisy&&) { std::cout << "M-assign" << std::endl; return *this; }
~Noisy() { std::cout << "Destructor" << std::endl; }
};
class Text {
public:
Text(Noisy&& text) : _text(std::move(text)) {}
operator const Noisy&() const { return _text; }
private:
Noisy _text;
};
int main() {
Text text(Noisy{});
const auto& s = static_cast<Noisy>(text); // Needs 'const' to bind to temporary.
}
Default construct
Move construct
Destructor
Copy construct
Destructor
Destructor
int main() {
Text text(Noisy{});
auto& s = static_cast<const Noisy&>(text);
}
Default construct
Move construct
Destructor
Destructor
Note: Compiled using option -fno-elide-constructors
to avoid copy elision optimizations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With