可以初始化但未分配的对象

时间:2017-02-01 08:32:39

标签: c++ initialization variable-assignment

我需要创建一个类,其对象可以初始化但不能分配。

我想也许我可以通过不定义赋值运算符来做到这一点,但编译器使用构造函数来完成赋值。

我需要这样:

Object a=1;    // OK
a=1;           // Error

我该怎么做?

5 个答案:

答案 0 :(得分:58)

制作const Object a=1; // OK const 可以解决问题

a

现在,由于a被声明为const,您将无法为a分配任何值。请注意,如果您将const声明为a,则必须在声明时初始化a

const声明为a并初始化后,您将无法将任何其他值分配给 a=1; //error

addItems

答案 1 :(得分:49)

您可以delete分配运算符:

#include <iostream>
using namespace std;

struct Object
{
    Object(int) {}
    Object& operator=(int) = delete;
};

int main()
{
    Object a=1;    // OK
    a=1;           // Error
}

替代解决方案

您可以使用explicit关键字:

#include <iostream>
using namespace std;

struct Object
{
    explicit Object(int) {}
};

int main()
{
    Object a(1);    // OK - Uses explicit constructor
    a=1;           // Error
}

<强>更新

正如用户2079303在评论中提到的那样:

  

值得一提的是,替代解决方案不会阻止常规复制/移动分配,例如a=Object(1)

使用以下内容可以避免这种情况:Object& operator=(const Object&) = delete;

答案 2 :(得分:13)

  

我希望通过不定义赋值运算符

来实现这一点

这不起作用,因为隐式生成了复制赋值运算符(以const Object&作为参数)。当您编写a = 1时,将尝试调用生成的复制赋值运算符,并且1可以通过转换构造函数Object隐式转换为Object::Object(int);然后a = 1;工作正常。

您可以声明赋值运算符明确地将int作为deleted(从C ++ 11开始);将在重载分配操作符之前在重载分配操作符中选择。

  

如果函数超载,则首先进行重载解析,如果选择了删除的函数,则程序只会格式错误。

e.g。

struct Object {
    Object(int) {}
    Object& operator=(int) = delete;
};

还有一些其他副作用的解决方案。您可以将Object::Object(int)声明为explicit,以禁止从intObject的隐式转换,然后使a = 1失败。但请注意,这会使Object a = 1;失败,因为复制初始化并不考虑explicit构造函数。或者您也可以删除复制赋值运算符,但这会使Object之间的赋值也失败。

答案 3 :(得分:9)

  

我该怎么做?

选项1:

制作构造函数explicit

struct Object
{
   explicit Object(int in) {}
};

选项2:

delete赋值运算符。

struct Object
{
   Object(int in) {}
   Object& operator=(int in) = delete;
};

您可以使用上述两个选项。

struct Object
{
   explicit Object(int in) {}
   Object& operator=(int in) = delete;
};

选项3:

如果您在初始化后不想要任何分配,则可以delete Object作为参数类型的赋值运算符。

struct Object
{
   explicit Object(int in) {}
   Object& operator=(Object const& in) = delete;
};

这将阻止使用:

Object a(1);
a = Object(2); // Error
a = 2;         // Error

答案 4 :(得分:7)

删除的函数仅在C ++ 11以后可用,对于较旧的编译器,您可以使用赋值运算符private

struct Object
{
Object(int) {}
private: 
Object& operator=(int);
};

编译器现在会抛出错误

Object a=1; //ok
a=2; // error 

但你仍然可以

Object a=1,b=2;
b=a;

因为编译器不会阻止默认赋值运算符生成。因此,标记默认分配private将解决此问题。

struct Object
{
Object(int) {}
private: 
Object& operator=(Object&);
};