As the subject, the related code is listed below.You could check it on https://godbolt.org/z/bcf8js.
There is no doubt that EntityId_t c_SEDSubscribe(ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER);
calls the user defined constructor EntityId_t(int id)
whereas I think EntityId_t c_SEDPPubWriter = ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER
; should call the user defined constructor EntityId_t(int id)
and movement assignment operator, but it's not this case since the terminate output.
In another word, I think ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER calls the user defined constructor EntityId_t(int id) to produce a temporary object.Since it's a rvalue(temporary object), complier then calls the movement assigment operation.Where am i wrong? I would be grateful to have some help with this question.
#include<string.h>
#include<iostream>
#define ENTITYID_UNKNOWN 0x00000000
#define ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER 0x000003c2
#define ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER 0x000003c1
struct EntityId_t
{
static constexpr unsigned int size = 4;
char value[size];
//! Default constructor. Uknown entity.
EntityId_t(){
*this = ENTITYID_UNKNOWN;
}
EntityId_t(int id)
{
int* aux = (int*)(value);
*aux = id;
std::cout << "EntityId_t(int id) constructor" << std::endl;
}
/*!
* @brief Copy constructor
*/
EntityId_t(
const EntityId_t& id)
{
memcpy(value, id.value, size);
std::cout << "copy constructor" << std::endl;
}
EntityId_t& operator =(
const EntityId_t& id)
{
memcpy(value, id.value, size);
std::cout << "copy operator() constructor" << std::endl;
return *this;
}
/*!
* @brief Move constructor
*/
EntityId_t(
EntityId_t&& id)
{
memmove(value, id.value, size);
std::cout << "move constructor" << std::endl;
}
EntityId_t& operator =(
EntityId_t&& id)
{
memmove(value, id.value, size);
std::cout << "move operator(EntityId_t&&)" << std::endl;
return *this;
}
};
int main()
{
EntityId_t c_SEDPPubWriter = ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER;
std::cout << "==============================" << std::endl;
EntityId_t c_SEDSubscribe(ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER);
}
ClassName var{foo};
This directly calls the constructor, passing in foo
.
ClassName var = foo;
This attempts implicit conversion of foo
to ClassName
, and requires that such a mechanism be available. This could be a non-explicit conversion constructor on ClassName
or a non-explicit operator ClassName
on foo
's type. If no such implicit conversion can be found, this is a compile-time error.
If a conversion can be found:
var
from it if possible, or copy-construct if move-construction is not possible. Pretty much all compilers will elide the move/copy, but such a constructor is still required to exist and be callable.We can prove this with a simple test case:
class Example {
public:
Example(int) {}
Example(Example const &) = delete;
Example(Example &&) = delete;
};
int main() {
Example b = 0;
(void)b; // Just silencing the unused variable warning
}
Compiling in C++14 mode yields:
main.cpp: In function 'int main()':
main.cpp:10:17: error: use of deleted function 'Example::Example(Example&&)'
10 | Example b = 0;
| ^
Compiling in C++17 mode succeeds, indicating that no copy- or move-construction is attempted.
Note that the results are the same when the conversion happens because of an operator Example()
present on the source value's type.
I post the answer which has been deleted by somebody quickly.But i think it's right.
should call the user defined constructor EntityId_t(int id) and movement assignment operator
In concept, the constructor EntityId_t(int id) is called to construct a temporary object, which is used to initialize the object; in this case the move constructor would be used but not move assignment operator.
Because of copy elision, the last step (move constructor calling) might be omitted then both two ways get same effect: the object is initialized by the constructor EntityId_t(int id) directly. Since C++17 copy elision is mandatory, before C++17 copy elision is an optimization, even the move constructor is not called, it still must be usable.
User contributions licensed under CC BY-SA 3.0