【问题标题】:C++ Return temporary values and objects that cannot be copiedC++ 返回无法复制的临时值和对象
【发布时间】:2014-02-04 22:37:28
【问题描述】:

我知道引用可以在 C++ 中使用extend the lifetime of a return value。有了这个哲学,我尝试了以下方法:我有三个类,“张量”、“视图”和“可变视图”。张量上的 Operator () 返回一个“const view”对象。该视图有一个私有的复制构造函数,因此该视图不能被复制,因为它保留了有关可能无法在当前语句之外存在的张量的信息。

#include <iostream>
#include <algorithm>

struct tensor {

  int data[10];

  class view {
    const int *const data;

    view();
    view(const view &);
  public:
    view(const int *new_data) : data(new_data) {}
    int operator*() const { return *data; }
  };

  class mutable_view {
    int *const data;

    mutable_view();
    mutable_view(const mutable_view &);
  public:
    mutable_view(int *new_data) : data(new_data) {}

    void operator=(const view &v) {
      *data = *v;
    }
  };

  tensor(int n) {
    std::fill(data, data+10, n);
  }

  const view operator()(int ndx) const {
    return view(data + ndx);
  }

  mutable_view at(int ndx) {
    return mutable_view(data + ndx);
  }
};


int main()
{

  tensor a(1);
  tensor b(2);

  b.at(2) = a(2);

  for (int i = 0; i < 10; i++)
    std::cout << "a[i] = " << b.data[i] << std::endl;

  for (int i = 0; i < 10; i++)
    std::cout << "b[i] = " << b.data[i] << std::endl;

  exit(0);
}

问题在于,虽然这段代码在 gcc 中工作(取决于版本),但 icc 发出警告,而 open64 根本不构建它:它要求“视图”中的构造函数是公共的。阅读 icc 的消息,这个想法似乎是编译器可能会复制右手的值,因此需要构造函数。

这是真的吗?是否有一种解决方法可以保留我想要构建的语法?顺便说一句,它们是构建的,为了避免基于 shared_ptr 或其他东西的低效实现,我需要保持“视图”对象不可复制。

编辑 1:

张量无法控制视图的生命周期。视图由访问者创建,它们的生命周期仅限于使用它们的语句,原因如下:

  • 这些视图仅用于两件事:(i) 复制数据,(ii) 提取部分张量。
  • 张量是实现写时复制语义的多维数组,这意味着视图不能是长期存在的对象:如果数据发生变化,它们就会过期。

编辑 2:

更改了伪代码描述(伙计们,如果您看到“...”,您认为它是可编译的吗?)使用基于 'icc' 而不是基于 clang/open64 的伪代码描述

【问题讨论】:

  • 您能否发布一个 SSCCE(请参阅 sscce.org)。我很惊讶 gcc 编译了这个。
  • const view operator(int idx)?似乎不是运算符重载。operator 是关键字。
  • 你想说operator ()(int idx)吗?
  • 当然这不是原始代码。我没有写 SSCCE,而是对它的外观有所了解。
  • 不要按 const 值返回。它仅用于禁用某些复制省略优化

标签: c++ reference return-value


【解决方案1】:

继续,让默认的复制构造函数公开。并记录 viewmutable_view 在其 tensor 更改或销毁时“无效”。

这与标准库如何处理具有依赖于另一个对象的生命周期的迭代器、指针和引用类似。

【讨论】:

  • 是的,这似乎是唯一的选择:-/ 很遗憾,我希望 C++ 强大的语法有助于检测此类错误。
【解决方案2】:

正如其他人已经指出的那样,您在这里错过了 ():

const view operator(int ndx) const;

无论如何,这个声明意味着返回值被复制。如果您想避免复制,只需返回对象的引用:

const view& operator()(int ndx) const;

据我了解,“张量”是“视图”的容器,因此它可以管理生命周期并且可以安全地返回参考。出于同样的原因,tensor::at 应该返回对 mutable_view 的引用:

mutable_view& at(int ndx);

另一个问题是关于“视图”的默认构造函数 - 看起来“张量”必须是“视图”的朋友才能创建其实例

顺便说一下 - 更喜欢使用 'size_t' 作为索引类型,而不是仅仅使用 'int'

我对这段代码的总体感觉——你正在尝试实现一种领域语言。也许专注于具体的计算任务会更好?

【讨论】:

  • 只有viewmutable_view对象是临时的,所以不能通过引用返回。
  • 我不明白你所说的“具体计算任务”是什么意思,但这是我正在开发的一个库,可以替代 Matlab (github.com/juanjosegarciaripoll/tensor) 在这方面,我们需要能够将数组的各个部分复制到其他数组中并针对目标受众(对编程知识很少或根本没有的物理学家)我确实需要 operator= 和 operator() 语法和写时复制语义。
猜你喜欢
  • 1970-01-01
  • 2016-10-10
  • 2013-10-24
  • 1970-01-01
  • 2019-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-30
相关资源
最近更新 更多