【问题标题】:C++ - Return C++11 std::arrayC++ - 返回 C++11 std::array
【发布时间】:2017-10-13 23:33:42
【问题描述】:

我有一些类似的代码

#define SIZE 10
Class User
{
public:
    std::array<Account, SIZE> getListAccount()
    {
         return listAccount;
    }
private:
    std::array<Account, SIZE> listAccount
}

Class Account
{
public:
    void setUserName(std::string newUSN)
    {
        userName=newUSN;
    }
private:
    string userName;
    string password;
}


int main()
{
     User xxx(.......);
     xxx.getListAccount()[1].setUserName("abc");    // It doesn't effect
     return 0;
}

为什么 main 中的 setUserName() 函数调用不更改我的 xxx 用户中的名称?

顺便说一句:

  • 我正在使用std::array,因为我想将数据保存在二进制文件中
  • 在我的实际代码中,我使用的是 char [],而不是字符串

【问题讨论】:

  • 您的 getter 返回数组的副本,因此名称只是在副本中更改,而不是在原始中。
  • 你需要问一个具体的问题,从表述上看你真正想要的是什么。绝对不想返回数组或对它的引用。
  • 您粘贴了无效的 C++ 代码:class 必须全部小写,并且您需要在 std::array&lt;Account, SIZE&gt; 中使用之前定义 class Account,并且您错过了三个 ; -- 请阅读如何提供minimal reproducible example!此外,为了减少名称污染,请避免使用#define。而是声明 static const size_t SIZE=10;enum {SIZE=10}; (甚至可以在要使用它的类中完成)。

标签: c++ arrays c++11 reference


【解决方案1】:

返回对列表的引用

std::array<Account, SIZE> & // << Note the &
User::getListAccount();

或者更好,不要暴露内部结构

Account&
User::getUser(size_t n) 
{
    return listAccount[n];
}

【讨论】:

  • 在界面上暴露实体的核心通常不是一个好主意(有很多原因)。
  • 使用索引复制用户中的帐户功能也是可能的。对我来说,与 getUser 方法相比,没有明显的赢家。太多的重复可能会变得混乱,太多的吸气剂也是如此。
【解决方案2】:
std::array<Account, SIZE> getListAccount() const {
     return listAccount;
}

这会返回数组的副本

std::array<Account, SIZE>& getListAccount() {
     return listAccount;
}
std::array<Account, SIZE> const& getListAccount() const {
     return listAccount;
}

这会返回对数组的引用。

template<class T>
struct span_t {
  T* b = 0; T* e = 0;
  span_t()=default;
  span_t(T* s, T* f):b(s),e(f){}
  span_t(T* s, std::size_t l):span_t(s, s+l){}
  T* begin() const{ return b; }
  T* end() const{ return e; }
  T& operator[](std::size_t i)const{ return begin()[i]; }
  std::size_t size() const { return end()-begin(); }
  bool empty() const { return begin()==end(); }
};

span_t<Account> getListAccount() {
  return {listAccount.data(), listAccount.size()};
}
span_t<const Account> getListAccount() const {
  return {listAccount.data(), listAccount.size()};
}

这会返回一个围绕一对指针的包装器,这些指针表示一系列连续的帐户,而不会暴露用于存储帐户的底层数据结构。

在这三个中,我会使用span_t。它的开销几乎为零,并且隐藏了客户不感兴趣的信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-23
    • 1970-01-01
    • 2012-12-20
    • 1970-01-01
    • 2021-11-15
    • 2016-02-08
    相关资源
    最近更新 更多