为什么我不能初始化一个对象数组,如果他们有私人拷贝构造函数? [英] Why can't I initialize an array of objects if they have private copy constructors?

查看:186
本文介绍了为什么我不能初始化一个对象数组,如果他们有私人拷贝构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在处理C ++项目时,我碰到了一些意想不到的令人沮丧的行为。我的实际代码有点复杂,但下面的例子也捕获它:

  class Irritating 
{
public:Irritating(){}
private:Irritating(const Irritating& other){}
};

常常刺激单身人士; //工作得很好。
const刺激数组[] = {Irritating()}; //编译错误。

int main()
{
return 0;
}

试着编译这个会产生以下错误(GCC版本抛出以防万一):

  [holt @ Michaela irritating] $ g ++ --version 
g ++(GCC)4.6.3 20120306( Red Hat 4.6.3-2)
版权所有(C)2011自由软件基金会,
这是自由软件;请参阅复制条件的来源。没有任何b $ b保修;甚至不适用于适销性或针对特定用途的适用性。

[holt @ Michaela irritating] $ g ++ test.cpp
test.cpp:4:11:error:'Irritating :: Irritating(const Irritating&)'是private
test.cpp:8:41:error:在这种情况下
[holt @ Michaela irritating]



不幸的是,这个令人讨厌的对象来自外部图书馆,并且在我的控制之外。我目前的解决方法是使用指针数组;它的工作原理,但它感觉有点ha and,并增加了一个不必要的间接层。有没有更好的方法来做到这一点?



另外:该数组是恒定的和全局的(在实际代码中,是类静态的)。为什么它没有被初始化?这是预期的C ++行为还是GCC的错误/怪癖?



更新:安装了Clang,看看它是否符合GCC。不幸的是,它确实:

  [holt @ Michaela irritating] $ clang test.cpp 
test.cpp:8: 29:警告:C ++ 98在绑定一个临时引用时需要一个可访问的复制构造函数,用于'Irritating'类;是私人的
[-Wbind-to-temporary-copy]
const刺激数组[] = {Irritating()};
^
test.cpp:4:11:note:这里声明为private
private:Irritating(const Irritating& other){}
^
test.cpp: 8:29:error:调用一个类的私人构造函数'Irritating'
const Irritating array [] = {Irritating()};
^
test.cpp:4:11:注意:这里声明为private
private:Irritating(const Irritating& other){}
^
1个警告和1个产生错误。
[holt @ Michaela irritating]


解决方案

因为单个数组元素是由通过= {...} 语法指定的初始化程序初始化的 copy-initialization 来初始化的。见8.5 / 12(C ++ 03)


初始化发生在参数传递,函数返回,
抛出异常(15.1),处理异常(15.3)和
大括号初始化列表(8.5.1)被称为复制初始化

复制初始化需要复制构造函数(即使它不会实际使用它)。



实际上,如果您通过复制构造函数public,编译器可能会最终初始化您的数组元素,而不使用复制构造函数。尽管如此,抽象语言的正式规则要求在这种情况下进行复制初始化。

I just ran across some unexpected and frustrating behaviour while working on a C++ project. My actual code is a tad more complicated, but the following example captures it just as well:

class Irritating
{
    public:  Irritating() {}
    private: Irritating(const Irritating& other) {}
};

const Irritating singleton;                // Works just fine.
const Irritating array[] = {Irritating()}; // Compilation error.

int main()
{
    return 0;
}

Trying to compile this produces the following error (GCC version thrown in just in case):

[holt@Michaela irritating]$ g++ --version
g++ (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2)
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

[holt@Michaela irritating]$ g++ test.cpp
test.cpp:4:11: error: ‘Irritating::Irritating(const Irritating&)’ is private
test.cpp:8:41: error: within this context
[holt@Michaela irritating]$ 

The offending object, unfortunately, is from an external library and outside my control. My current workaround is to use an array of pointers; it works, but it feels a bit hackish and adds a needless layer of indirection. Is there a better way to do this?

Also: The array is constant and global (well, class-static in the actual code); why isn't it being initialized in place? Is this expected C++ behaviour, or a bug/quirk of GCC?

Update: Installed Clang just to see if it would agree with GCC. Sadly, it did:

[holt@Michaela irritating]$ clang test.cpp
test.cpp:8:29: warning: C++98 requires an accessible copy constructor for class 'Irritating' when binding a reference to a temporary; was private
      [-Wbind-to-temporary-copy]
const Irritating array[] = {Irritating()};
                            ^
test.cpp:4:11: note: declared private here
        private: Irritating(const Irritating& other) {}
                 ^
test.cpp:8:29: error: calling a private constructor of class 'Irritating'
const Irritating array[] = {Irritating()};
                            ^
test.cpp:4:11: note: declared private here
        private: Irritating(const Irritating& other) {}
                 ^
1 warning and 1 error generated.
[holt@Michaela irritating]$

解决方案

Because individual array elements are initialized by copy-initialization from the initializers specified through = {...} syntax. See 8.5/12 (C++03)

The initialization that occurs in argument passing, function return, throwing an exception (15.1), handling an exception (15.3), and brace-enclosed initializer lists (8.5.1) is called copy-initialization

Copy-initialization requires copy constructor (even if it won't actually use it).

In practice, if you make your code compile by making the copy constructor public, the compiler will probably end up initializing your array elements in place, without using the copy constructor. Nevertheless, the formal rules of abstract language call for copy-initialization in this context.

这篇关于为什么我不能初始化一个对象数组,如果他们有私人拷贝构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆