Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Deleted copy assignment operator vs. trivial copy assignment operator

30 views
Skip to first unread message

bitrex

unread,
Apr 11, 2017, 11:58:16 AM4/11/17
to
Suppose I have a class such as:

class Foo
{
public:
Foo(std::stack<Bar>& ref1, Baz *const ref2) :
_ref1(ref1), _ref2(ref2)
{}

// etc.

private:
std::stack<Bar>& _ref1;
Baz *const _ref2;
};

The standard says (for C++11):

"A defaulted copy assignment operator for class T is defined as deleted
if any of the following is true:

T has a non-static data member of non-class type (or array thereof) that
is const;

T has a non-static data member of a reference type;

T has a non-static data member or a direct or virtual base class that
cannot be copy-assigned (overload resolution for the copy assignment
fails, or selects a deleted or inaccessible function);

T is a union-like class, and has a variant member whose corresponding
assignment operator is non-trivial."

It also says:

"The copy assignment operator for class T is trivial if all of the
following is true:

it is not user-provided (meaning, it is implicitly-defined or
defaulted), , and if it is defaulted, its signature is the same as
implicitly-defined (until C++14);

T has no virtual member functions;

T has no virtual base classes;

the copy assignment operator selected for every direct base of T is trivial;

the copy assignment operator selected for every non-static class type
(or array of class type) member of T is trivial.

A trivial copy assignment operator makes a copy of the object
representation as if by std::memmove. All data types compatible with the
C language (POD types) are trivially copy-assignable."



Which of these situations takes precedence for a class like my example?
It does contain a reference, yet given that it has no other fields other
than what are essentially pointers which aren't allowed to change, a
std::memmove should work fine for copying it.

red floyd

unread,
Apr 11, 2017, 12:28:28 PM4/11/17
to
On 4/11/2017 8:58 AM, bitrex wrote:
> Suppose I have a class such as:
>
> class Foo
> {
> public:
> Foo(std::stack<Bar>& ref1, Baz *const ref2) :
> _ref1(ref1), _ref2(ref2)
> {}
>
> // etc.
>
> private:
> std::stack<Bar>& _ref1;
> Baz *const _ref2;
> };
>
> The standard says (for C++11):
>
> "A defaulted copy assignment operator for class T is defined as deleted
> if any of the following is true:
>
> T has a non-static data member of non-class type (or array thereof) that
> is const;
>
[redacted]

I'm no language guru, but it seems to me that _ref2 is a non-static data
member of non-class type that is const.


Bonita Montero

unread,
Apr 11, 2017, 2:08:31 PM4/11/17
to
> std::memmove should work fine for copying it.

LOL!

Alf P. Steinbach

unread,
Apr 11, 2017, 2:28:07 PM4/11/17
to
[c:\Temp]
> type foo.cpp
#include <stdio.h>

struct X
{
int& ref;
};

auto main()
-> int
{
int gosh = 42;
X a{ gosh }, b{ gosh };
a = b;
}

[c:\Temp]
> g++ foo.cpp
foo.cpp: In function 'int main()':
foo.cpp:13:9: error: use of deleted function 'X& X::operator=(const X&)'
a = b;
^
foo.cpp:3:8: note: 'X& X::operator=(const X&)' is implicitly deleted
because the default definition would be ill-formed:
struct X
^
foo.cpp:3:8: error: non-static reference member 'int& X::ref', can't use
default assignment operator

[c:\Temp]
> _


> std::memmove should work fine for copying it.

Lols. :)


Cheers & hth.,

- Alf

bitrex

unread,
Apr 12, 2017, 11:42:14 AM4/12/17
to
On 04/11/2017 02:27 PM, Alf P. Steinbach wrote:

> [c:\Temp]
>> _
>
>
>> std::memmove should work fine for copying it.
>
> Lols. :)
>
>
> Cheers & hth.,
>
> - Alf
>

This seems to work fine (at least on my architecture and compiler.)
Though is probably undefined behavior. At least from a "C++ outsider's"
perspective, why you couldn't at least from a theoretical implementation
standpoint memmove a class whose fields consisted solely of immutable
pointers or aliases for such and otherwise met the requirements for
being trivially copyable escapes me.

#include <stack>
#include <cstring>
#include <iostream>

struct Foo
{
Foo(std::stack<int>& thing1,
int *const thing2) :
_thing1(thing1),
_thing2(thing2)
{}

std::stack<int>& _thing1;
int *const _thing2;
};

int main()
{
std::stack<int> a;
std::stack<int> b;
int c = 5;
int *const d = &c;
int e = 6;
int *const f = &e;

a.push(c);
b.push(e);

auto bar = Foo(a, d);
auto baz = Foo(b, f);

std::cout << *bar._thing2 << std::endl;
std::cout << *baz._thing2 << std::endl;
std::cout << bar._thing1.top() << std::endl;
std::cout << baz._thing1.top() << std::endl;

std::memmove(&bar, &baz, sizeof(Foo));

std::cout << *bar._thing2 << std::endl;
std::cout << *baz._thing2 << std::endl;
std::cout << bar._thing1.top() << std::endl;
std::cout << baz._thing1.top() << std::endl;
}
0 new messages