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

Gal*_*ian 29 c++ initialization variable-assignment

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

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

我需要它是这样的:

Object a=1;    // OK
a=1;           // Error
Run Code Online (Sandbox Code Playgroud)

我该怎么做?

You*_*saf 58

使a const成为可能

const Object a=1;    // OK
Run Code Online (Sandbox Code Playgroud)

现在,你将不能够为任意值分配给a作为a被声明为const.请注意,如果您声明aconst,则必须a在声明时初始化.

一旦你已经声明aconst也初始化它,你将不能为任何其他值赋给a

 a=1;   //error
Run Code Online (Sandbox Code Playgroud)

  • +1虽然其他答案解决了OP在他们的段落中提出的问题,但我的直觉说这是他们实际上*意味着要问的问题. (10认同)
  • 如果您希望它应用于`Object`的所有实例,请在一个(或多个)成员变量上使用`const`.Voila,默认情况下删除了赋值运算符. (3认同)

Jon*_*nas 49

您可以删除赋值运算符:

#include <iostream>
using namespace std;

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

int main()
{
    Object a=1;    // OK
    a=1;           // Error
}
Run Code Online (Sandbox Code Playgroud)

替代方案

您可以使用explicit关键字:

#include <iostream>
using namespace std;

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

int main()
{
    Object a(1);    // OK - Uses explicit constructor
    a=1;           // Error
}
Run Code Online (Sandbox Code Playgroud)

更新

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

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

这可以通过使用: Object& operator=(const Object&) = delete;


son*_*yao 13

我希望通过不定义赋值运算符来实现这一点

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

你可以声明赋值运算符取int删除(因为C++ 11)明确; 将在重载分配操作符之前在重载分配操作符中选择.

如果函数过载,则首先发生重载解析,如果选择了删除的函数,则程序只会格式错误.

例如

struct Object {
    Object(int) {}
    Object& operator=(int) = delete;
};
Run Code Online (Sandbox Code Playgroud)

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

  • 在`= delete`之前,我们将它声明为私有而永远不会定义它.或者使用Boost的便捷混音. (2认同)

R S*_*ahu 9

我该怎么做?

选项1:

制作构造函数 explicit

struct Object
{
   explicit Object(int in) {}
};
Run Code Online (Sandbox Code Playgroud)

选项2:

delete 赋值运算符.

struct Object
{
   Object(int in) {}
   Object& operator=(int in) = delete;
};
Run Code Online (Sandbox Code Playgroud)

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

struct Object
{
   explicit Object(int in) {}
   Object& operator=(int in) = delete;
};
Run Code Online (Sandbox Code Playgroud)

选项3:

如果在初始化后不需要任何赋值,delete则赋值运算符可以Object作为参数类型.

struct Object
{
   explicit Object(int in) {}
   Object& operator=(Object const& in) = delete;
};
Run Code Online (Sandbox Code Playgroud)

这将阻止使用:

Object a(1);
a = Object(2); // Error
a = 2;         // Error
Run Code Online (Sandbox Code Playgroud)


小智 7

删除的函数仅从C++ 11开始提供,对于较旧的编译器,您可以创建赋值运算符private.

struct Object
{
Object(int) {}
private: 
Object& operator=(int);
};
Run Code Online (Sandbox Code Playgroud)

编译器现在会抛出错误

Object a=1; //ok
a=2; // error 
Run Code Online (Sandbox Code Playgroud)

但你仍然可以做到

Object a=1,b=2;
b=a;
Run Code Online (Sandbox Code Playgroud)

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

struct Object
{
Object(int) {}
private: 
Object& operator=(Object&);
};
Run Code Online (Sandbox Code Playgroud)