Constructor with By-Value Parameter & Noexcept

Constructor with by-value parameter & noexcept

The construction and destruction of function parameters happens in the context of the caller. So no, if the construction of text throws, that is not a violation of noexcept.

Soon folks would comment and ask for a spec quote :) So I will give you 5.2.2p4

The initialization and destruction of each parameter occurs within the context of the
calling function.

Function with by-value return & noexcept

To answer part of your question, you can ask whether a certain type is nothrow constructible:

#include <type_traits>

MyType MyFunction( SomeType const &x )
noexcept(std::is_nothrow_move_constructible<MyType>::value)
{
// ....
}

Where are exceptions thrown when arguments are passed by value

See C++17 [expr.call]/4

... The initialization and destruction of each parameter occurs within the context of
the calling function. [ Example: The access of the constructor, conversion functions or destructor is checked at the point of call in the calling function. If a constructor or destructor for a function parameter throws an exception, the search for a handler starts in the scope of the calling function; in particular, if the function called has a function-try-block (Clause 18) with a handler that could handle the exception, this handler is not
considered. — end example ]

So the exception is, as you would put it, thrown "outside of the function". You can declare it noexcept.

return by value and noexcept

After the edit: Your implementation of operator- is guaranteed not to throw any exception (well, at least if you mark operator* as noexcept, that is), and it is thus safe to mark it as noexcept. I don't really understand your concern, though so I might be missing the reason for the question. All of the operations, including the potential copy or move construction are explicitly marked noexcept... where is the issue?


Unless you explicitly mark it as noexcept it will not have that qualification. Now, depending on the implementation of operator* and the copy-constructor it might actually never throw, but that does not make it noexcept.

As of the copy-constructor, if you don't define it, the implicitly declared copy constructor will be noexcept or not depending on whether all the members of your type are noexcept (again, not only that they don't throw, but that they have that qualification)

Who manages the exception thrown by a copy constructor in parameters?

See [expr.call]/4:

The initialization and destruction of each parameter occurs within the context of
the calling function. [ Example: The access of the constructor, conversion functions or destructor is checked at the point of call in the calling function. If a constructor or destructor for a function parameter throws an exception, the search for a handler starts in the scope of the calling function; in particular, if the function called has a function-try-block (Clause 18) with a handler that could handle the exception, this handler is not considered. —end example ]

Therefore you can still mark foo noexcept, even though the initialization of bar might throw. The calling function should not be noexcept. (That is, unless you're ok with the program being terminated in case of an exception.)

IDE recommends 'pass by value and use std move' when parameter class has no move constructor

Your Person class is following the "rule-of-zero", meaning it doesn't declare any copy/move operations or destructor explicitly.

That is usually the correct thing to do, because then the compiler will declare all of them implicitly and define them with the semantics you would usually expect from the these operations, if that is possible.

In your case, all members of Person can be move-constructed, so the implicit move constructor of Person will be defined to move-construct the members one-by-one.

This is what is used when you add std::move in mData(std::move(data)). Without it data is a lvalue and instead the implicit copy constructor which copy-constructs each member would be used.

Copy-constructing a std::string is often more costly than move-constructing it, which is probably why the tool warns about that case, but not if std::string isn't there. Move-constructing and copy-constructing an int member is exactly the same operation.

If you don't want to check each time what members a class has, you can simply always use std::move in these situations. For example changing mId(id) to mId(std::move(id)) is pointless, because id is a scalar type, but it also doesn't make anything worse.

How to reference move constructor in noexcept operator

The operator noexcept() needs a true expression. Unfortunately T(T&&) is not a valid expression.

So you'd need to instantiate an occurrence of T and use std::move() to make sure it uses the move constructor if there's one. Here a proof of concept:

template <typename T> 
struct TypeInfo
{
bool test()
{
T t;
bool IsNothrowMoveConstructible = noexcept(T(std::move(t)));
return IsNothrowMoveConstructible;
};
};

The problem is that this becomes much more error prone. If T has no default constructor, it will fail to compile. Same if move constructor was implicitly or explicitly deleted.

But if you can live with these flaws, as the value is determined at compile time and is therefore constant, you could use a T member and define a constant in an enum:

struct TypeInfo 
{
T t;
enum {
IsNothrowMoveConstructible = noexcept(T(std::move(t)))
};
};

Here an online demo.

Why is passing by value (if a copy is needed) recommended in C++11 if a const reference only costs a single copy as well?

When consuming data, you'll need an object you can consume. When you get a std::string const& you will have to copy the object independent on whether the argument will be needed.

When the object is passed by value the object will be copied if it has to be copied, i.e., when the object passed is not a temporary. However, if it happens to be a temporary the object may be constructed in place, i.e., any copies may have been elided and you just pay for a move construction. That is, there is a chance that no copy actually happens.



Related Topics



Leave a reply



Submit