[libcxx-dev] std::vector using copy constructor on existing elements during reserve()

Richard Smith via libcxx-dev libcxx-dev at lists.llvm.org
Mon Apr 29 01:54:43 PDT 2019


On Wed, 17 Apr 2019 at 16:44, Duncan Exon Smith <dexonsmith at apple.com> wrote:
> On 2019 Apr  17, at 11:06, Louis Dionne <ldionne at apple.com> wrote:
>
>
>
> On Apr 17, 2019, at 13:38, JF Bastien <jfbastien at apple.com> wrote:
>
>
>
> On Apr 17, 2019, at 10:12 AM, Louis Dionne via libcxx-dev <libcxx-dev at lists.llvm.org> wrote:
>
>
>
> On Apr 17, 2019, at 12:39, Duncan P. N. Exon Smith <dexonsmith at apple.com> wrote:
>
> I'm curious about how people feel this should/could behave with -fno-exceptions.  IIRC, Libc++ calls the copy constructor (following the standard), but -fno-exceptions isn't really standard, and from a user perspective that doesn't make sense.  `noexcept` is essentially meaningless with -fno-exceptions.
>
>
> I personally feel like it would be surprising if -fno-exceptions caused the move constructor to be called instead of the copy constructor. My mental model is that -fno-exceptions only disables exceptions as a language feature, but doesn't really instruct libraries to provide a different API (even though the difference in this case is very small). Instead, I feel like it would make more sense if "everything" was implicitly marked noexcept when -fno-exceptions is used (because that's really the case). The library would behave optimally with -fno-exceptions without having to do anything special.
>
>
> IIUC what you’re saying: the library should just use the noexcept operator to do its business, and it seem like -fno-exceptions should make noexcept always return true? That would be pretty consistent (more than teaching the library about -fno-exceptions for move / copy).
>
>
> Yes, that's what I mean. I agree with Eric that moving instead of copying provides value, but I think the right way to do it is not to special case libc++, but instead to have all code bases become better under -fno-exceptions by making noexcept do the right thing.
>
>
> Yeah, that makes sense to me too.
>
> +Richard, I could have sworn you and I chatted quickly about this back in 2016 by my mail-search-fu is failing me.  What are your thoughts on having -fno-exceptions affect the value of `noexcept`?

Here are some questions I'd want to have answers to:
 * How does this impact GCC compatibility?
 * How does this impact the size and performance of generated code?
 * Would an exception result in a guaranteed call to terminate like in
a real noexcept function, or undefined behavior as in today's
-fno-exceptions?
 * What's the impact on C++17 code, now that 'noexcept' is part of the
type system? Given
    void f();
    ... is that a function with a  non-noexcept function type, with
noexcept(f()) being true, or is the type of f also adjusted to 'void()
noexcept'? Both answers seem troublesome.
 * What migration strategy do we provide or encourage, in order to
help people move away from the -fno-exceptions language dialect and
back to standard C++? How does this change enable / hinder that?

Longer-term, "Clang should drive the standard, not diverge from it"
(http://clang.llvm.org/get_involved.html). We should be thinking about
the long term direction of exceptions in C++, and in particular Herb's
P0709. In that vein (particularly considering P0709R2's footnote 10
and nearby text) I'm wondering if we should have an experimental
option to specify that functions are noexcept by default (overridable
by an explicit exception specification) as a bridge for
-fno-exceptions users to take back towards standard C++.

Regardless of whatever else we do, I think we should work to make use
of noexcept a viable alternative to today's -fno-exceptions. In
particular, that means fixing the longstanding issue that LLVM can't
model C++'s "you may choose to not unwind if unwinding would reach a
noexcept function" rule, which currently results in bad codegen for
noexcept functions compared to -fno-exceptions. Eg, compare clang and
GCC codegen with and without -fno-exceptions for:

struct X { ~X(); };
void g();
void f() noexcept {
    X x;
    g();
}

> Louis
>
>
> Thoughts?
>
> On Apr 16, 2019, at 23:19, Eric Fiselier via libcxx-dev <libcxx-dev at lists.llvm.org> wrote:
>
>
>
> On Tue, Apr 16, 2019 at 2:25 PM Michael Narigon via libcxx-dev <libcxx-dev at lists.llvm.org> wrote:
>>
>> std:vector is using the element copy constructor on existing elements during its resizing operation in reserve(). I would expect it to use the move constructor for efficiency. Is this intended behavior?
>
>
> Yes, this behavior is mandated by the standard. The copy constructor is used when the move constructor is not noexcept. From cppreference's `std::move_if_noexcept` documentation:
>
>> std::vector::resize, which may have to allocate new storage and then move or copy elements from old storage to new storage.
>> If an exception occurs during this operation, std::vector::resize undoes everything it did to this point, which is only possible if
>> std::move_if_noexcept was used to decide whether to use move construction or copy construction. (unless copy constructor is
>>
>> not available, in which case move constructor is used either way and the strong exception guarantee may be waived)
>
>  https://en.cppreference.com/w/cpp/utility/move_if_noexcept
>
> If you add `noexcept` to your move constructor, vector should call the move constructor.
>
>
>
>>
>>
>> This is with the libc++ delivered with Xcode 10.1.
>>
>> Attached is a sample program displaying the behavior.
>> _______________________________________________
>> libcxx-dev mailing list
>> libcxx-dev at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/libcxx-dev
>
> _______________________________________________
> libcxx-dev mailing list
> libcxx-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/libcxx-dev
>
>
>
> _______________________________________________
> libcxx-dev mailing list
> libcxx-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/libcxx-dev
>
>


More information about the libcxx-dev mailing list