4

Are undeclared (auto-generated) copy constructors automatically marked as inline?

If so, and if I don't want them to be marked as inline, does that mean I have to define one manually and copy every single member I need by hand (assuming I'm not using C++11, so that there's no = default to take advantage of)?

user541686
  • 205,094
  • 128
  • 528
  • 886
  • Intrigued... why would that matter? – K-ballo Jan 11 '13 at 20:30
  • @K-ballo: You wouldn't want to encouage inlining in some scenarios, like this: http://dev.chromium.org/developers/coding-style/cpp-dos-and-donts#TOC-Stop-inlining-constructors-and-destructors. – user541686 Jan 11 '13 at 20:31
  • 3
    @Mehrdad: You should not try to force the compiler to do things other than the way it was specifically chosen by the compiler writer to do them. You should not assume you know more about good code generation than the compiler's authors. Whether or not to inline undeclared copy-constructors is the compiler author's decision and if you think they made the wrong one, you should talk to them about it. – David Schwartz Jan 11 '13 at 20:32
  • @Mehrdad: That article you point is wrong, you just can't use incomplete types with standard containers – K-ballo Jan 11 '13 at 20:33
  • @K-ballo: Uh, sure, I didn't write the article, but you kind of missed the point. Pretend like they wrote `boost::container::vector` if that bothers you; the point is the same. – user541686 Jan 11 '13 at 20:34
  • 3
    @Mehrdad: You're not encouraging inlining. You're encouraging the compiler to make the best decision by giving it all the information and authority it needs to make the right decision. If your compiler makes bad decisions under those circumstances, stop using it or complain to its authors. It is absolute madness to make your code unnecessarily complex to try to work around a compiler bug or issue and certifiably insane to do so for a trivial performance issue. – David Schwartz Jan 11 '13 at 20:34
  • @DavidSchwartz: You should give your advice to the Chromium guys, not me. `inline` causes the compiler to bloat up the input to the linker, and yes, it **does** sometimes matter. I'm not sure what you mean by "you're not encouraging inlining" but I have certainly run across cases where saying `inline` makes a difference. – user541686 Jan 11 '13 at 20:34
  • @Mehrdad: Did they suggest manually defining copy constructors where the default will do?! If so, then I will! (By the way, I agree about inlining. Predictable jumps are cheap and code bloat hurts performance because of code cache usage.) – David Schwartz Jan 11 '13 at 20:35
  • @Mehrdad: I get _some_ of the point, then some other part of the point is just plain wrong (the inlined constructors forbid you from using standard containers with incomplete types part) – K-ballo Jan 11 '13 at 20:36
  • @K-ballo: Again, I'm not the one who wrote that article, so I'm not sure why you keep on telling me about the irrelevant issue. The point that the article was trying to make is well-founded even if the particular example is wrong. – user541686 Jan 11 '13 at 20:37
  • @DavidSchwartz: That was precisely why I asked this question to begin with -- I wondered why they would mention normal constructors but not copy constructors, and I'm thinking it's probably because declaring copy ctors is a pain and error-prone. I'm not sure why you keep on assuming that you (or the compiler writers) know about *every* situation... it's a fact that you don't know about the code as much as its authors, and also that bloated object files can link darn slow. If you've never tried it I suggest you put yourself in others' shoes and try it before pretending you've seen everything. – user541686 Jan 11 '13 at 20:42

4 Answers4

8

They're treated as if they were declared inline (which doesn't necessarily mean that they will be inlined). And yes, in pre-C++11, the only way to prevent their being inline was to declare and define them manually, copying every member and every base class explicitly in the initializer list.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • Can you make a non-inlined, defaulted constructor in C++11? – Kerrek SB Jan 11 '13 at 20:34
  • @KerrekSB Yes. The `= default` works for anything the compiler might generate. – James Kanze Jan 11 '13 at 20:37
  • @JamesKanze can you give an explicit example of a non-inlined, default constructor in C++11? – Yakk - Adam Nevraumont Jan 11 '13 at 21:01
  • 2
    @KerrekSB: If the question is whether adding `= default` implicitly marks as `inline`, it does or not depending on where it appears. If it is inside the class definition, it will be implicitly `inline`, but you can also *default* the definition of the function outside of the class definition in which case it will only be inline if you mark it as such (example: `struct X { X(); }; X::X() = default;`) – David Rodríguez - dribeas Jan 11 '13 at 21:02
  • 1
    @DavidRodríguez-dribeas: That's right, I get that - my question was essentially if that last construction is valid. I wasn't quite sure about the grammar for the `= default`. – Kerrek SB Jan 11 '13 at 21:41
  • Yeah I definitely hadn't seen that one either, thanks for the answer James! Your answers are extremely helpful. :) – user541686 Jan 11 '13 at 22:56
  • @DavidRodríguez-dribeas Thanks for the clarification. I actually hadn't thought it through to that point. – James Kanze Jan 12 '13 at 10:52
  • @Yakk Just about any default constructor that the user writes. Anytime you write the default constructor, and the implementation is not in the class itself. (And unless the class is very small and trivial, you probably don't want the implementation in the class, for readability reasons.) – James Kanze Jan 12 '13 at 10:53
  • @jameakanze if the user writes it, it isn't a `= default` constructor. – Yakk - Adam Nevraumont Jan 12 '13 at 11:16
  • @Yakk But it is a default constructor. Any constructor which can be called without any arguments is a default constructor. – James Kanze Jan 12 '13 at 11:31
  • That is now a bad name for it, by default. – Yakk - Adam Nevraumont Jan 12 '13 at 15:52
  • @Yakk That is its name, and always has been, since the earliest days of C++. What would you call it, if not? – James Kanze Jan 12 '13 at 15:57
  • @jameskanze Nullary constructor maybe? – Yakk - Adam Nevraumont Jan 13 '13 at 08:41
  • @Yakk I don't think nullary is a word. "Default" seems to fit the bill; it's the constructor which is called when you don't provide any arguments, to set the object to a default state. – James Kanze Jan 13 '13 at 13:34
  • http://en.m.wikipedia.org/wiki/Nullary_constructor or look up arity in general. It is a word, it applies, and with the existance of `= default` calling a non `=default` constructor the default constructor is a bad idea. – Yakk - Adam Nevraumont Jan 13 '13 at 13:44
  • There was no `= default` when the concept of default constructor was introduced. And default constructor describes very well what it is. (Given your definition, a nullary constructor is something else. A default constructor can have arguments, as long as they all have defaults.) – James Kanze Jan 13 '13 at 14:02
  • @Yakk: if it helps you deal with the cognitive burden, then the constructor called with `()` is the default constructor, whereas a constructor defined with `= default` has the default implementation. So they're different things, although of course a particular example could be both: the default constructor can have the default implementation. Next, keyword `static`. – Steve Jessop Jun 07 '15 at 00:33
6

Yes. From C++11, 12.8/11:

An implicitly-declared copy/move constructor is an inline public member of its class.

I would strongly suggest reading all of 12.8 if you like to get more familiar with copy and move constructors.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
1

They are, I believe. However, for a such a compiler-defined function, the difference between inline and not is non-observable. And yes, you would have to define your own for it to be non-inline, although why you would want such a thing is beyond me. It makes no difference to the semantics and won't affect the compiler's inlining.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • 1
    It could very well affect whether the compiler inlines it or not. Most compilers today inline just about everything they can (in optimizing mode, at least). Very few, however, will inline a function whose source is not in the same translation unit. – James Kanze Jan 11 '13 at 20:34
  • @JamesKanze: Right, but that's an issue to take up with compiler writers. You definitely shouldn't modify your code to prevent the compiler from inlining in cases where the compiler thinks it should. – David Schwartz Jan 11 '13 at 20:38
  • It also affects the semantics; compilers can't *completely* ignore the word `inline`. Maybe you **don't** want to violate the ODR by using `inline`, in which case your only option is to not declare the method as `inline`, regardless of whether or not you like inlining. – user541686 Jan 11 '13 at 20:47
  • @Mehrdad: Your last comment is wrong in that it is built on the premise that the keyword `inline` means **inline**. The keyword `inline` means *it is not an ODR violation if this symbol is defined multiple times in a program*. – David Rodríguez - dribeas Jan 11 '13 at 22:33
  • Huh? How is my comment saying otherwise? I never said `inline` forces inlining; I said if you avoid `inline`, then it makes you avoid violating the ODR. Not sure what was wrong there... even the Chromium style guide says, *"**Every file** that has to use an `inline` method will also emit a function version in the resulting .o, even if the method was inlined. (This is to support function pointer behaviour properly.)"* – user541686 Jan 11 '13 at 22:39
  • @DavidRodríguez-dribeas In general, I agree with you. You should write the code for the reader, and leave it up to the compiler to inline or not, depending on the options you give it. In practice, compilers aren't that good yet, and you sometimes will want to specify inline, as a hint to the compiler and to make the source available in all translation units. The same thing holds in reverste: if you find that the compiler's inlining is causing undesirable code bloat, you might want to do something to prevent it. – James Kanze Jan 12 '13 at 10:50
  • @JamesKanze: As far as I'm aware, *most* compilers can perform LTO now. – Puppy Jan 12 '13 at 12:55
  • @Mehrdad: It doesn't affect the semantics for you. The method exists and the compiler takes care of it's definition and declaration, and that's it. There are no semantics in the code that are different for you whether the compiler chooses to declare it and stick a definition in some implementation-defined TU, or whether it defines it inline. – Puppy Jan 12 '13 at 12:55
  • 1
    @DeadMG In theory, yes. In practice, it's not commonly used. – James Kanze Jan 12 '13 at 15:02
  • @DeadMG: You do realize that LTO compiles **all** the code in **one** pass, right? You can't take advantage of parallel compilation with it, and it's *very* I/O intensive. Really, unless you are doing *the* final build of your product with it, it's not useful. Try it with a project like Chromium and your disk is going to thrash around and your RAM is going to get used up like there's no tomorrow. (Many gigabytes. And no, I don't have *that* much RAM to spare on my laptop.) Really, the mere *existence* of a feature doesn't automatically invalidate a question that doesn't use it. – user541686 Jan 12 '13 at 19:23
1

Implicitly defined special member functions are inline and they must be as they can be implicitly generated in multiple translation units. The meaning of inline is that it can be defined in multiple translation units without violating the ODR, not that the code will actually be inlined (this depends on the type and the compiler).

Why don't you want the copy constructor to be inline?

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • Must be is a bit strong. The problem isn't any different than that of template functions. – James Kanze Jan 11 '13 at 20:34
  • @JamesKanze: How could a implicitly defined function not be `inline`?(with the meaning of `inline` in the standard). Consider it was not, then if the compiler generated the non-inline function in two different translation units, it would break the ODR rule, as there would be multiple definitions of the same symbol in the executable. Or am I missing something? – David Rodríguez - dribeas Jan 11 '13 at 21:04