C++ 返回不可复制的临时值和对象

标签 c++ reference return-value

我知道引用可以extend the lifetime of a return value在 C++ 中。有了这个哲学,我尝试了以下方法:我有三个类,“tensor”、“view”和“mutable_view”。张量上的运算符 () 返回一个“常量 View ”对象。此 View 有一个私有(private)复制构造函数,因此无法复制该 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 根本不构建它:它要求“ View ”中的构造函数是公开的。阅读 icc 的消息,这个想法似乎是右手值可能会被编译器复制,因此需要构造函数。

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

编辑 1:

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

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

编辑 2:

更改了伪代码描述(伙计们,如果你看到“...”,你认为它是可编译的吗?)用一个建立在“icc”上而不是在 clang/open64 上的伪代码描述

最佳答案

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

这类似于标准库处理迭代器、指针和引用的方式,这些迭代器、指针和引用的生命周期取决于另一个对象。

关于C++ 返回不可复制的临时值和对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21565030/

相关文章:

c++随机无法解释的错误

c++ - 如何从另一个运行整个 CPP 文件?

c++ - 将 char[] 转换为 unsigned int 得到 : dereferencing type-punned pointer will break strict-aliasing rules

c++ - 此构造函数初始化程序是否会导致悬空引用?

sql - 在 PostgreSQL 中实现没有触发器的复杂引用

javascript - 面向对象 JS : variable passing/referencing query

c++ - DLIB 是用于在 C++ 中开发我自己的机器学习算法的良好开源库吗?

javascript - 为什么 ?函数的对象参数返回未定义的 JS

Java调用方法并捕获返回

java - 返回 NULL 的替代方法