【问题标题】:Is it possible to define a 'move-and-swap idiom' equivalent in C++03是否可以在 C++03 中定义等效的“移动和交换习语”
【发布时间】:2020-02-19 09:14:20
【问题描述】:

我绑定到 C++03 并且我有一个不可复制的对象(例如持有资源)。

我需要使用 move-and-swap 语义来做类似的事情并避免复制:

MyClass returnMyClass(void)
{
    MyClass temp;
    // fill 'temp' members with actual data
    return temp;
}

int main(void)
{
    MyClass test;
    test = returnMyClass(); // need to avoid copies
}

是否可以在 C++03 中遵守所有这些要求?

this的情况基本一样,只不过是针对C++03。


换句话说:

给定一个不可复制MyClass,在C++03中是否有可能做到MyClass test = returnMyClass();

恐怕答案很简单,但也许我错过了一些技巧。

【问题讨论】:

  • 不清楚为什么你不使用构造函数而不是makeClass
  • 如果您的意思是“如果类不可复制,您能否使用语法return test 从函数返回test,这是一个自动存储持续时间的变量?”答案是不。在 C++03 中,该 return 语句隐式调用复制构造函数,如果编译器检测到它无法调用该构造函数,则需要诊断错误。 main() 中的test() 的定义还需要一个可访问的复制构造函数。即使编译器省略了临时变量也是如此——C++03 编译器不需要这样做。
  • 将您的复制构造函数设为私有。编写一个自定义的move() 函数并转移底层元素的所有权。
  • MyClass test = makeClass() 在您的示例中是初始化。没有副本。
  • @Peter 这正是我想问的,我编辑了示例代码以消除歧义并澄清问题。我不是要使用方法而不是构造函数,也不是要初始化。

标签: c++ move c++03


【解决方案1】:

移动语义没有魔法。这只是另一个超载。右值引用的东西是一个很好的便利,并不是很重要。

template <class T>
struct rref { 
    rref (T& t) : t(t) {}
    T& t; 
};

template<class T>
rref<T> move(const T& t) {
   return rref<T>(const_cast<T&>(t));
}

// you now can do a "move ctor"
class Foo {
   Foo(rref<Foo>) { ... }
};

现在,您还需要 NRVO 才能使此功能发挥作用。标准不保证它,但几乎每个实现都提供它。为确保它真正发生,您可以声明但不定义复制 ctor。

Full working demo

【讨论】:

  • 是的,除了你的提案修改了我班级的客户端(即主函数)。我想做的正是Foo foo = make_foo();,而不是Foo foo = move(make_foo());。抱歉,不清楚。
  • 这可能用于初始化,也可能不用于初始化,但肯定不能用于赋值或传递函数参数。
  • 如果Foorref&lt;Foo&gt; 提供了一个转换运算符,这可以工作吗? IINM,这就是 first move 仿真提议和 Boost.Move 真正做的事情。
  • @LuisMachuca 它可以工作,但我认为隐式转换太危险了。
【解决方案2】:

如果您可以在声明时初始化您的对象test,您将能够避免复制,因为将执行复制省略。

class MyClass
{
  public:
    MyClass(){std::cout << "Default Constructor" << std::endl;}
    MyClass(const MyClass &){std::cout << "CPYConstructor" << std::endl;}
    ~MyClass() {std::cout << "Destructor" << std::endl;}

};


MyClass returnMyClass(void)
{
    MyClass temp;
    // fill 'temp' members with actual data
    return temp;
}

int main(void)
{
    MyClass test = returnMyClass(); // need to avoid copies
}

输出:

Default Constructor
Destructor

【讨论】:

  • 问题不在于复制省略,问题在于 C++03 编译器仍然需要复制 ctor (MyClass(const MyClass &amp;)),而我确实想要定义因为我的类是不可复制的。
猜你喜欢
  • 2011-10-13
  • 1970-01-01
  • 2012-01-15
  • 1970-01-01
  • 2020-05-27
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 2011-09-05
相关资源
最近更新 更多