20

Moving can't be implemented efficiently (O(1)) on std::array, so why does it have move constructor ?

5
  • 9
    std::array doesn't have any constructors except the defaults generated by the compiler. Commented Aug 7, 2013 at 13:47
  • 1
    Where did you get this wrong piece of information (that std::array has a move constructor)? Commented Aug 7, 2013 at 13:47
  • 1
    @R.MartinhoFernandes the compiler-generated move constructor. Commented Aug 7, 2013 at 13:56
  • 11
    Just because moving the whole array isn't O(1) doesn't mean it's not useful to gain O(1) in moving each element. Commented Aug 7, 2013 at 14:17
  • 9
    The unhelpful answer is "Of course std::array has an O(1) move constructor". All instantiations of std::array<int, 5> take the same time to move/copy. std::array<int, 6>? That's a different type! Commented Aug 7, 2013 at 23:08

3 Answers 3

28

std::array has a compiler generated move constructor, which allows all the elements of one instance to be moved into another. This is handy if the elements are efficiently moveable or if they are only movable:

#include <array>
#include <iostream>

struct Foo
{
  Foo()=default;
  Foo(Foo&&)
  {
    std::cout << "Foo(Foo&&)\n";
  }
  Foo& operator=(Foo&&)
  {
    std::cout << "operator=(Foo&&)\n";
    return *this;
  }
};

int main()
{
  std::array<Foo, 10> a;
  std::array<Foo, 10> b = std::move(a);
}

So I would say std::array should have a move copy constructor, specially since it comes for free. Not to have one would require for it to be actively disabled, and I cannot see any benefit in that.

Sign up to request clarification or add additional context in comments.

5 Comments

Does it require that the element move constructor be nothrow? Or can it simply leave the operation in any legal state?
@MarkB good question, I hadn't considered it. This code works as is on gcc 4.7.3, even if I add a copy constructor. I will have to go read the standard, but my guess would be that a move from one container to the another cannot be expected to support the strong exception guarantee.
@juanchopanza: I believe you're right on the exception safety guarantee. That is, std::array move-constructor doesn't provide the strong exception safety guarantee. Only the basic one. See the first bullet of 12.8/15. My only doubt is if the "corrresponding subobject" is also an rvalue. What do you think?
@MarkB: "Does it require that the element move constructor be nothrow?" It's a compiler-generated move constructor, so it works with whatever it's given. If the underlying type is noexcept moveable, then the generated move constructor will be too. And if it isn't, then neither will the generated one be.
Isn't the answer supposed to be slightly more involved ? especially in the fact that an array, on the stack (possibly), cannot be pointer exchanged, therefore cannot be moved in O(1). The move constructor implicitely iterates over the elements of the aggregate and move each elements. This is not obvious, but the standard provides this powerful guarantee, the compiler expands quite a lot of hidden code here.
24

To summarize and expand on other answers, array<T> should be moveable (when T itself is moveable) because:

  • T may be efficiently moveable.
  • T may be move-only.

4 Comments

lol, this says nothing. "should" "may" "may"... at least do you mean "should" by standard ?
@v.oddou This is stating why the fact that array<T> is movable (for movable T) makes sense.
@juanchopanza: this is just a letter to santa claus. this was already obvious prior to the question. yes we want what is stated. now we want to know facts about whether it is or not, and why.
Oh, actually, after re-reading your question I get it now. The question was "should" therefore the answer repeats the term, so its enough by itself. OK, approved. lol
0

Have a look at the standard:

23.3.2.2 array constructors, copy, and assignment [array.cons]

The conditions for an aggregate (8.5.1) shall be met. Class array relies on the implicitly-declared special member functions (12.1, 12.4, and 12.8) to conform to the container requirements table in 23.2. In addition to the requirements specified in the container requirements table, the implicit move constructor and move assignment operator for array require that T be MoveConstructible or MoveAssignable, respectively.

The move constructor and assignment operator are by far not free, they may not be provided.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.