g ++和非const复制构造函数问题

时间:2012-03-08 17:32:41

标签: c++ g++ copy-constructor

在构建FOO对象时是否可以告诉g ++使用FOO&运算符?

struct FOO {

        FOO( FOO & foo ) { // non-const copy constructor
        }

        operator FOO&() {

                return *this;
        }

        FOO( int i ) {
        }
};


int main() {

        FOO a(FOO(5));
}

我目前收到以下错误:

In function int main():
  error: no matching function for call to FOO::FOO(FOO)
  note: candidates are: FOO::FOO(int)
  note:                 FOO::FOO(FOO&)

- 编辑 -

请注意,我尝试设置一个可以交换资源所有权的对象 调用FOO foo1(foo)使foo失去资源的所有权,这意味着foo不能是const
另请注意,我想避免使用智能指针机制。

2 个答案:

答案 0 :(得分:3)

您的转换运算符永远不会被接收。

§12.3.2 [class.conv.fct] p1

  

转换函数永远不会用于将(可能是cv限定的)对象转换为(可能是cv限定的)相同的对象类型(或对它的引用),转换为(可能是cv限定的)基类类型(或对它的引用),或(可能是cv-qualified)void。

原因是此处提到的转化(cv void除外)已经通过所谓的标准转化完成(资格转换(添加const或{{ 1}})和身份转换(将对象绑定到引用))和标准转换始终优先于用户定义的转换:

volatile

  

标准转换序列(13.3.3.1.1)是比用户定义的转换序列更好的转换序列[...]


对于您的特定情况,如果您想转移所有权,请使用移动构造函数以C ++ 11样式执行此操作。

§13.3.3.2 [over.ics.rank] p2

通过非const拷贝构造函数传递所有权是一个非常糟糕的主意,因为这样的类型永远不能存储在标准容器中,请参阅丑陋的#include <utility> // move struct foo{ int resource; foo(int r) : resource(r) {} foo(foo&& other) : resource(other.resource) { other.resource = 0; } }; int main(){ foo f1(foo(5)); //foo f2(f1); // error foo f3(std::move(f1)); // OK } (在C ++ 11中替换为std::auto_ptr ,具有适当的移动语义)。

答案 1 :(得分:1)

  

请注意,我尝试设置一个可以交换资源所有权的对象。

     

调用FOO foo1(foo)使foo失去资源的所有权,这意味着foo不能是const。

     

另请注意,我想避免使用智能指针机制。

所以你有类似的东西:

struct FOO {
        // ...
        SomeType* storage;
        bool owns_storage;
        // ...
        FOO(const FOO& foo): storage(foo.storage), owns_storage(true) {
            foo.owns_storage = false; /* <-- fails to build */ }
        ~FOO() { if(owns_storage) delete storage; }
};

您需要一份副本才能在owns_storage原始对象上将false设置为const。使用mutable关键字,您的问题就会消失:

struct FOO {
        // ...
        SomeType* storage;
        mutable bool owns_storage;
        // ...
        FOO(const FOO& foo): storage(foo.storage), owns_storage(true) {
            foo.owns_storage = false; /* builds fine now */ }
        ~FOO() { if(owns_storage) delete storage; }
};