24

For example, I want to declare a class but I want the client to not be able to use the copy constructor (or copy assignment operator)

Both of the following two does not allow the use of the copy constructor:

1.

class Track
{
public:
  Track(){};
  ~Track(){};
private:
  Track(const Track&){};
};

2.

class Track
{
public:
  Track(){};
  ~Track(){};
  Track(const Track&)=delete;
};

Is one of these ways "more correct" than the other or are equal? Is there any side-effect?

//Does not compile with both the above ways
int main()
{
  Track l;
  Track p(l);
}
4

7 回答 7

19

Making it private is the "old" way of doing it. The constructor still exists, but it is private, and can only be invoked from within another class member function.

= delete deletes the constructor. It is not generated by the compiler, and it simply will not exist.

So most likely, = delete is what you want. (although with the caveat that not all compilers support this syntax yet, so if portability is a concern...)

于 2013-05-26T10:26:16.127 回答
8

Declaring a copy constructor private still allows member functions of the Track class to copy-construct instances of that class, while making it deleted simply forbids copy-constructing that object.

In C++11, deleting a copy constructor is the right way to express the fact that a class is non-copyable (unless of course it makes sense for you to let member functions of Track, or friends of Track, to copy-construct Track objects).

于 2013-05-26T10:25:56.257 回答
5

Making a constructor private was basically a "hack" in the old C++, since it was the only way to prevent users from using them. The ability to delete special member functions was only introduced in C++11, and it's the better and more idiomatic way to say that a class cannot be copied. since it is explicit about the intention.

Private constructors have other uses other than forbidding their use entirely (e.g. they may be called by static class member functions). So just making a constructor private doesn't communicate the intention very well, and the resulting error is not very clear, either.

于 2013-05-26T10:26:21.150 回答
0

Your first approach doesn't prevent the class itself from copying itself. The traditional way to solve this is to declare the copy-constructor private and to leave it unimplemented.

An issue with that, however, is that the intent might not be obvious. Someone reading the code might not understand why an orphaned declaration exists and might mistakenly remove it. Comments can help, as would privately inheriting from boost::noncopyable if Boost is available to you.

The second approach makes the intent obvious and is what you should prefer if you can use C++11.

于 2013-05-26T10:26:38.483 回答
0

Your first solution conveys to the reader that the copy-constructor is private and is not to be used. Your second solution is only valid in C++11. Because of this, I'd say the more portable and readable implementation would be your first, using the private-property.

于 2013-05-26T10:27:24.960 回答
0

If you are on C++11, use delete. The reason is that it makes the call explicit and the intent clear. You could still accidentally use a private constructor (e.g. in a restricted set of scopes), but the compiler will forbid you from ever using a deleted constructor.

One issue of the private constructor is that the class and friends can still use it -- this results not in access errors but link errors, which can be hard to trace back to the callsite.

If your necessary toolchains do not support deleted constructors (= delete), you should not define it (as seen in your question) -- only declare it and leave it undefined, e.g.: private: \n Track(const Track&);

于 2013-05-26T10:29:17.480 回答
0

在第一种情况下,您实际上是在声明一个私有复制构造函数,然后不提供任何实现。通过将它们声明为私有,非成员不能复制它。

在第二种情况下,语法禁止制作副本。这是 C++ 原生的。

作为程序员的主要区别在于可读性和对代码的理解。第一种情况是多余的,为什么要声明复制构造函数,使其私有,而不是实现它。客户必须在这里推断很多。

您可以只使用“= delete”并清楚地暗示您要做什么。

于 2013-05-26T10:30:02.643 回答