Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/jenkins/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在堆栈上为非默认可构造文件保留空间?_C++_Allocation_Default Constructor - Fatal编程技术网

C++ 如何在堆栈上为非默认可构造文件保留空间?

C++ 如何在堆栈上为非默认可构造文件保留空间?,c++,allocation,default-constructor,C++,Allocation,Default Constructor,我将基本上编写以下代码。我理解它为什么不能编译 A instance; // A is a non-default-constructable type and therefore can't be allocated like this if (something) { instance = A("foo"); // use a constructor X } else { instance = A(42); // use *another* constructor Y }

我将基本上编写以下代码。我理解它为什么不能编译

A instance; // A is a non-default-constructable type and therefore can't be allocated like this

if (something)
{
    instance = A("foo"); // use a constructor X
}
else
{
    instance = A(42); // use *another* constructor Y
}

instance.do_something();

有没有办法实现这个行为而不涉及堆分配?

< P>在一些简单的情况下,你可以逃脱这个标准C++语法:

A instance=something ? A("foo"):A(42);
您没有指定正在使用的编译器,但在更复杂的情况下,可以使用
gcc
编译器特定扩展:

A instance=({
       something ? A("foo"):A(42);
});

假设要多次执行此操作,可以使用帮助器函数:

A do_stuff(bool flg)
{
  return flg ? A("foo") : A(42);
}
然后

否则,可以使用条件运算符表达式*进行初始化:



*这是一个示例,说明了条件运算符如何“不象
if else

这是一项新的工作,尽管如果您重新审视您的需求,几乎可以肯定有更简单的解决方案

#include <iostream>

struct A
{
    A(const std::string& str) : str(str), num(-1)  {};
    A(const int num)          : str(""),  num(num) {};

    void do_something()
    {
        std::cout << str << ' ' << num << '\n';
    }

    const std::string str;
    const int num;
};

const bool something = true;   // change to false to see alternative behaviour

int main()
{
    char storage[sizeof(A)];
    A* instance = 0;

    if (something)
        instance = new (storage) A("foo");
    else
        instance = new (storage) A(42);

    instance->do_something();
    instance->~A();
}
#包括
结构A
{
A(conststd::string&str):str(str),num(-1){};
A(const int num):str(“”),num(num){};
空做某事
{

有比显式保留堆栈上的空间更好、更干净的方法来解决问题,例如使用条件表达式

但是,如果类型不可移动构造,或者您有更复杂的条件,这意味着您确实需要在堆栈上保留空间,以便稍后在两个不同的位置构造某些内容,那么您可以使用下面的解决方案

标准库提供了
aligned_storage
特性,因此
aligned_storage::type
是一种大小和排列正确的POD类型,用于存储
T
,因此您可以使用它来保留空间,然后使用placement new将对象构造到该缓冲区中:

std::aligned_storage<A>::type buf;
A* ptr;
if (cond)
{
  // ...
  ptr = ::new (&buf) A("foo");
}
else
{
  // ...
  ptr = ::new (&buf) A(42);
}
A& instance = *ptr;
或者使用lambda,尽管这会浪费堆栈上的额外指针;-)

std::实验::可选foo;
如果(条件){
炮位(arg1,arg2);
}否则{
foo.emplace(zzz);
}
然后使用
*foo
进行访问。
boost::optional
如果没有C++1z TS实现,或者编写自己的
optional

在内部,它将使用std对齐存储和
bool
来保护“我是否已创建”;或者可能使用
union
。编译器可能会证明不需要
bool
,但我对此表示怀疑


实现可以从下载,也可以使用。

您是否也为
a
提供了复制构造函数和赋值运算符?同样,在这种情况下,您最好为类属性提供getter/setter函数,并提供默认构造函数。最简单的解决方案似乎是使用指针。您是否有理由不使用需要它在堆栈上吗?把它推到一个向量中?你不能做
一个实例(“”;
?那么它必须是可复制可构造的。@user3528438或move可构造的。但是OP对这两者都没有要求。如果它真的是一个一次性函数,它可以是lambda。@Angew或只是
一个实例=某个东西?a(“foo”):a(42);
关于“复杂情况”的更多信息,请问?第一个表单在什么情况下不起作用?@user3528438,如果您在创建
A
对象之前需要完整的语句。条件运算符只允许表达式,GCC扩展允许任意块。@user3528438:您自己在juanchopanza的回答中指出了一个问题:如果
A
不是copy construct那么这个代码是非法的。这就是lambda的用途,甚至是一个helper函数。它是移动可构造的,擦洗。好吧,这比我的弱放置新尝试要好得多。谁会在放置构造函数之后调用析构函数?@LightnessRacesinOrbit,是的,如果
char
buffer isn不适合对齐。这是一个手动条件表达式/lambda,它太笨了。juanchopanza似乎是唯一注意到明显的语言提供的解决方案的人。@Puppy,问题是如何在堆栈上保留空间,所以这就是我的答案。如果类型是可移动构造的,并且条件表达式可以工作,那就是这是OP应该使用的,但是如果条件的两个分支需要多个语句,那么
对齐的\u存储
+放置新解决方案仍然有效。
#include <iostream>

struct A
{
    A(const std::string& str) : str(str), num(-1)  {};
    A(const int num)          : str(""),  num(num) {};

    void do_something()
    {
        std::cout << str << ' ' << num << '\n';
    }

    const std::string str;
    const int num;
};

const bool something = true;   // change to false to see alternative behaviour

int main()
{
    char storage[sizeof(A)];
    A* instance = 0;

    if (something)
        instance = new (storage) A("foo");
    else
        instance = new (storage) A(42);

    instance->do_something();
    instance->~A();
}
std::aligned_storage<A>::type buf;
A* ptr;
if (cond)
{
  // ...
  ptr = ::new (&buf) A("foo");
}
else
{
  // ...
  ptr = ::new (&buf) A(42);
}
A& instance = *ptr;
struct destroy_A {
  void operator()(A* a) const { a->~A(); }
};
std::unique_ptr<A, destroy_A> cleanup(ptr);
std::unique_ptr<A, void(*)(A*)> cleanup(ptr, [](A* a){ a->~A();});
struct Cleanup {
  A* a;
  ~Cleanup() { a->~A(); }
} cleanup = { ptr };
std::experimental::optional<Foo> foo;
if (condition){
  foo.emplace(arg1,arg2);
}else{
  foo.emplace(zzz);
}