4

假设我有这个结构

struct MyStruct {

  static MyStruct Create(int x) {
    return { x*2, x>3 };
  }

  MyStruct(const MyStruct& c) = delete;  // no copy c'tor

private:
  MyStruct(int a_, bool b_) : a(a_), b(b_) {}  // private c'tor -- can't use new

  const int a;
  const bool b;
};

编辑:我删除了复制构造函数。这是我在我的代码库中没有复制 c'tors 的一些类的简化示例。

我可以像这样在堆栈上获取一个实例:

int main() {
  auto foo = MyStruct::Create(2);
  return 0;
}

但是假设我需要一个指针(或者unique_ptr很好),并且我无法更改 的实现MyStruct,我该怎么做?

4

5 回答 5

4

您可以包装MyStruct在另一个具有MyStruct成员的类中。这是它的最小版本:

class Wrapper {
public:
    MyStruct ms;
    Wrapper(int x) : ms(MyStruct::Create(x)) { }
};

您可以像这样使用它:

int main() {
  MyStruct::Create(2);
  std::make_unique<Wrapper>(2);
}

此代码不会触发任何复制或移动- 因为复制省略(请参阅:什么是复制省略和返回值优化?)。

然后,您可以将您喜欢的任何其他构造函数和方法添加到此类包装器中,可能会将某些方法调用转发给ms成员。有些人可能会选择设置为ms受保护的或私有的。

于 2021-10-07T20:34:20.227 回答
2

这是你要找的吗?

auto baz  = std::make_unique<MyStruct>( MyStruct::Create(2) );  // unique pointer
于 2021-10-07T20:34:49.667 回答
1

评论而不是答案,以避免给未来的读者造成混淆。

我可以像这样在堆栈上获取一个实例:

int main() {
  auto foo = MyStruct::Create(2);
  return 0;
}

请注意,这仅适用于 C++17 并保证复制省略,而 C++14 的程序格式错误,因为即使可以省略复制,初始化foo也是从临时的复制初始化 (在 C++17 中:临时永远不会实现)。

于 2021-10-07T21:28:04.173 回答
0

另一种方法:

  struct ChildStruct : public MyStruct {                                                                                  
      ChildStruct(int x) : MyStruct(MyStruct::Create(x))                             
      {}                                                                             
                                                                                     
  };                                                                                 
                                                                                     
  int main() {                                                                       
    MyStruct *foo1 = new ChildStruct(2);                                             
    return 0;                                                                        
  }  
于 2021-10-07T20:50:59.733 回答
0

C 风格的解决方案。我不确定这不是 UB,但对于具有 2 个整数字段的简单结构,它应该可以工作。

int main() {                                                                    
    auto foo = MyStruct::Create(2);                                               
                                                                                  
    MyStruct *p = (MyStruct*)malloc(sizeof(MyStruct));                            
    memcpy(p, &foo, sizeof(MyStruct));                                            
    //...
    free(p);
    return 0;                                                                     
}
于 2021-10-07T21:12:45.363 回答