【问题标题】:creating a type which can be initialized with assignment, but is not copyable创建一个可以通过赋值初始化但不可复制的类型
【发布时间】:2012-09-04 18:36:29
【问题描述】:

我希望创建一种类型,该类型可以使用其他类型的赋值进行初始化,但不能复制。这个想法类似于作用域智能指针,因为我希望这种类型的对象在其生命周期内拥有资源,但我也希望能够使用赋值语法。所以总而言之,这就是我想要的:

T x = new U; // allowed
T y(new U);  // allowed
T z = x;     // not allowed
T x2(x)      // not allowed

这是我迄今为止尝试过的......

#include <boost/noncopyable.hpp>

class U {};

class T : boost::noncopyable {
public:
    T(U *p) : p_(p) {
    }

    ~T() {
        delete p_;
    }

    operator bool() const { return p_ != 0; }

private:
    U *p_;
};

int main() {
    T x = new U; // allowed
    T y(new U);  // allowed
    //T z = x;     // not allowed
    //T x2(x)      // not allowed
}

不幸的是,这会导致错误:

$ g++ test.cc -o test /usr/include/boost/noncopyable.hpp:复制中 构造函数'T::T(const T&)': /usr/include/boost/noncopyable.hpp:27:7: 错误:'boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable&)' 是私有 test.cc:6:30: 错误: 在此上下文中 test.cc: 在函数'int main()'中: test.cc:20:12: 注意:这里首先需要合成方法'T::T(const T&)'

注意:C++11 的移动功能对我来说不是一个选项,因为它必须能够使用不支持 C++11 的相对较旧版本的 gcc 进行编译。

由于缺乏对 C++11 的支持,我不确定是否有“好的”解决方案。但我想我会问。

【问题讨论】:

  • 只需将复制构造函数设为私有即可。
  • @Chris:您还没有阅读我的问题,复制构造函数已经 私有的。这就是boost::noncopyable 所做的。我需要它是不可复制的,但我也希望它可以用赋值语法初始化。
  • T y = x where x is not a T is the same as T y(T(x)) IIRC (not T y(x)),所以你必须有如果你想允许这个 pre C++11,则复制构造函数 public
  • Seth 是正确的,T x = y;复制初始化 的特定语法(顺便说一句,与赋值无关没有)。跨度>
  • @eq- 即使发生复制省略,复制构造函数也必须是可访问的,编译器优化不能规避语言规则

标签: c++


【解决方案1】:

如果我对 cme​​ts 的理解是正确的 - 你想要这样的东西:

U* create_T() { return new U; }
if (T t = create_T())
{
  // do something with t
}

这里的问题,在 cmets 中已经提到:这个语法T t = u 只是调用复制构造函数。如果 u 的类型为 T,则它等价于:T t(u)。如果u,就像你的例子一样,是另一种可转换为There by T::T(U*))的类型,那么它实际上是:T t(T(u))。所以在这里你有编译器抱怨的复制构造函数。

没有解决办法,因为这是无效的if语法:

if (T i(create_T())) {}

但是,如果没有好的建议,我不会写所有这些 ;)

您可以忘记使用以下语法的复制构造函数的问题:

if (U* u = create_T()) {
   T t(u);
   ....
} 

顺便说一句,std::auto_ptr 与您的 T 类型有相同的问题。只需将显式添加到您的 T(U*) 构造函数中,您就会看到与 auto_ptr 的相似之处:

class U {};

class T : boost::noncopyable {
public:
    explicit T(U *p) : p_(p) {
    }

    ~T() {
        delete p_;
    }

private:
    U *p_;
};

int main() {
    T x = new U; // allowed
    T y(new U);  // allowed
    std::auto_ptr<U> a = new U;
    std::auto_ptr<U> b(new U);
}

结果:

prog.cpp:25: error: conversion from ‘U*’ to non-scalar type ‘T’ requested
prog.cpp:27: error: conversion from ‘U*’ to non-scalar type ‘std::auto_ptr<U>’ requested

这里是我的ideone 书房...

【讨论】:

  • @Evan,顺便说一句 - 它对你有用吗:if (U* u = create_T()) { T t(u);}?如果不是 - 编写复制构造函数。您可以使 p_ 可变以从复制的 const 对象中获取所有权。
  • 您的建议肯定会“奏效”。语法不是我想要的,但它确实实现了我想要的基本概念,所以你得到 +1。我将把这个问题留一会儿,看看是否有人想出一些聪明的东西:-)。
  • 谢谢。我不确定它是否聪明——但看看我的 ideone 链接。我添加了带有可变 p_ 和 InitT 结构的新解决方案。然而,这打破了你不允许复制构造的目标......
  • @EvanTeran 你好。你看我记得这个问题,我觉得这会起作用:for (T t(create_T()); t;) { ...; break; }。 for-loop 是唯一一个在使用“constructor-way”构造变量时没有这种限制的循环。
猜你喜欢
  • 2017-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-13
  • 2012-11-21
  • 2019-11-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多