标签: deleted-functions

为什么删除拷贝构造函数不允许使用具有多态类型的其他构造函数?

我想知道为什么这个程序不能编译(msvc,gcc和clang上的相同行为):

#include <iostream>

using namespace std;

struct Action
{
    virtual void action()
    {
        cout << "Action::action()\n";
    }
};

struct ActionDecorator : Action
{
    ActionDecorator(const ActionDecorator&) = delete;
    ActionDecorator(Action & action) : origAction(action)
    {
    }

    void action() override
    {
        decoration();
        origAction.action();
    }

private:
    void decoration()
    {
        cout << "ActionDecorator::decoration()\n";
    }

    Action & origAction;
};

int main()
{
    Action action;
    ActionDecorator actionDecorator(action);
    ActionDecorator actionDecorator2(actionDecorator);
    actionDecorator2.action();
}
Run Code Online (Sandbox Code Playgroud)

根据我的期望,删除的拷贝构造函数应该让其他ActionDecorator实例构造ActionDecorator,因为它是Action的多态类型.相反,我必须显式地将ActionDecorator实例转换为Action并且因为编译器抱怨尝试引用已删除的复制构造函数.是否有一些解释这种行为的标准规则?

c++ polymorphism copy-constructor deleted-functions

4
推荐指数
1
解决办法
140
查看次数

实例化std :: mutex时编译器错误

我在代码库中广泛使用了std :: mutex.但是,其中一个类只是不允许我在其实例变量列表中添加互斥锁.我正在使用以下内容简单地实例化互斥锁 -

std::mutex myMutex;
Run Code Online (Sandbox Code Playgroud)

我将上述语句添加到类成员列表的私有部分.

我收到以下错误 -

error C2280: 'std::mutex::mutex(const std::mutex &)' : attempting to reference a deleted function
1> C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\mutex(113) : see declaration of 'std::mutex::mutex'
Run Code Online (Sandbox Code Playgroud)

我试图添加互斥锁的类被复制.

正如我所说的,我在我的代码库中使用了互斥锁,所以我可以在一个地方实例化互斥锁,而我可以在所有其他地方实例化,这是非常奇怪的.你能告诉我这里出了什么问题吗?

c++ mutex std deleted-functions c++11

3
推荐指数
1
解决办法
2451
查看次数

为什么不能构造包含ostringstream成员的对象?

我有以下类示例,从较大的项目中简化.它基于一个日志框架,它使用记录器的作用域来终止析构函数中的日志条目.

下面的代码将无法编译,因为构造函数是一个隐式删除的函数(编辑:不是真),这似乎与std::ostringstream对象有关.我对此感到困惑,因为我认为我应该能够直接构造一个std::ostringstream,这意味着我应该能够直接构造一个Container对象.

#include <iostream>
#include <sstream>

class Container {
  public:
    std::ostringstream  bufferStream;

  public:
    Container();    // constructor
    ~Container();
};

Container::Container() {
    bufferStream << "Hello ";
}

Container::~Container() {
    std::cout << bufferStream.str() << " [end]" << std::endl;
}

// === Main method ===

int main() {

    Container().bufferStream << "world";   // works fine

    {                                      // causes tons of compiler errors
        Container cont = Container();
        cont.bufferStream << "world!";
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

请注意,标记为"正常工作"的行就是这样做的.它似乎实例化了一个匿名Container对象,它包含一个新的std::ostringstream …

c++ ostringstream deleted-functions c++11

3
推荐指数
1
解决办法
543
查看次数

合并两个unique_ptr向量时'使用已删除的函数'

我正在尝试合并两个向量unique_ptr(即std::move它们从一个到另一个),并且我继续遇到"使用已删除的函数..."错误文本的墙.根据错误,我显然试图使用unique_ptr已删除的复制构造函数,但我不确定原因.以下是代码:

#include <vector>
#include <memory>
#include <algorithm>
#include <iterator>

struct Foo {
    int f;

    Foo(int f) : f(f) {}
};

struct Wrapper {
    std::vector<std::unique_ptr<Foo>> foos;

    void add(std::unique_ptr<Foo> foo) {
        foos.push_back(std::move(foo));
    }

    void add_all(const Wrapper& other) {
        foos.reserve(foos.size() + other.foos.size());

        // This is the offending line
        std::move(other.foos.begin(), 
                  other.foos.end(), 
                  std::back_inserter(foos));
    }
};

int main() {
    Wrapper w1;
    Wrapper w2;

    std::unique_ptr<Foo> foo1(new Foo(1));
    std::unique_ptr<Foo> foo2(new Foo(2));

    w1.add(std::move(foo1));
    w2.add(std::move(foo2));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

c++ unique-ptr move-semantics deleted-functions c++11

3
推荐指数
1
解决办法
286
查看次数

为什么我使用删除的函数'void std :: ref(const _Tp &&)[with _Tp = int]'

#include<iostream>
#include<utility>
#include<tuple>
#include<functional>
using namespace std;
int main()
{
    int i = 0;
    auto p = make_pair(ref(i), ref(i++));
    p.first++;
    p.second++;
    cout << "i = " << i << endl;
}
Run Code Online (Sandbox Code Playgroud)

例如,如果我这样使用ref(),编译器会说

使用已删除的函数'void std :: ref(const _Tp &&)[with _Tp = int]'

但是,如果我的代码如下

#include<iostream>
#include<utility>
#include<tuple>
#include<functional>
using namespace std;
int main()
{
    int i = 0;
    auto p = make_pair(ref(i), ref(++i));
    p.first++;
    p.second++;
    cout << "i = " << i << endl;
}
Run Code Online (Sandbox Code Playgroud)

我会成功获得输出i = 3,所以我无法理解为什么我会得到如此不同的答案.

c++ move-constructor deleted-functions c++11

3
推荐指数
1
解决办法
1422
查看次数

“隐式删除”构造函数=删除还是根本没有声明?

给出以下玩具代码:

class X
{
public:
    X() { }
    X(const X&) { }
    //X(X&&) = delete;
};

int main()
{
    X x;
    X y = std::move(x);
}
Run Code Online (Sandbox Code Playgroud)

我知道X::X(X&&)在这种情况下它被隐式删除,因为它X(const X&)作为用户声明的构造函数存在。但我对这里术语“隐式删除”的含义有点困惑:如果我们取消注释,代码的行为会有所不同,这意味着隐式删除“显式”删除X(X&&) = delete;之间存在差异。

我心中有两种不同的理解:

  • “隐式删除”意味着编译器生成一些类似于的代码X(X&&) = delete;(也就是说,编译器知道存在X(X&&)并且知道它X(X&&)被删除),但生成的代码X(X&&) = delete;在某种程度上不同于,当X y = std::move(x);尝试调用时X::X(X&&),编译器选择X(const X&)而不是报告错误。(如果X(X&&) = delete;取消注释,编译器不会选择X(const X&),会报错)

  • “隐式删除”意味着X(X&&)根本没有在类中声明,换句话说,编译器没有任何有关的信息X(X&&),因此X y = std::move(x);直接与 …

c++ deleted-functions

3
推荐指数
1
解决办法
1193
查看次数

我怎样才能禁止在C++ 2011中调用rvalue对象的const成员函数?

以下代码

#include <vector>
#include <string>
#include <iostream>

std::string const& at(std::vector<std::string> const& n, int i)
{
    return n[i];
}

std::vector<std::string> mkvec()
{
    std::vector<std::string> n;
    n.push_back("kagami");
    n.push_back("misao");
    return n;
}

int main()
{
    std::string const& s = at(mkvec(), 0);
    std::cout << s << std::endl; // D'oh!
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

可能导致崩溃,因为原始矢量已经在那里被破坏.在引入rvalue-reference之后的C++ 2011(c ++ 0x)中,如果vector参数是rvalue ,则可以使用已删除的函数声明来完全禁止调用at

std::string const& at(std::vector<std::string>&&, int) = delete;
Run Code Online (Sandbox Code Playgroud)

这看起来不错,但以下代码仍会导致崩溃

int main()
{
    std::string const& s = mkvec()[0];
    std::cout << s << std::endl; // D'oh!
    return 0;
} …
Run Code Online (Sandbox Code Playgroud)

c++ rvalue deleted-functions c++11

2
推荐指数
1
解决办法
452
查看次数

错误C2280:尝试引用已删除的函数(尝试调用vector.erase)

我是C++的新手.我正在使用SFML和Box2D开发一个突破克隆,我在编译时遇到这个错误.错误详情:

c:\program files (x86)\visual studio express 2013\vc\include\xutility(2420): error C2280: 'Tile &Tile::operator =(const Tile &)' : attempting to reference a deleted function
c:\users\harry\documents\visual studio 2013\projects\cpp-breakout\cpp-breakout\entities\tile.hpp(27) : compiler has generated 'Tile::operator =' here
Run Code Online (Sandbox Code Playgroud)

当我尝试使用vector.erase从std :: vector <Tile>中删除Tile对象时出现错误.

Tile.h

class Tile : public Entity {
public:
    Tile(b2World* world, float posX, float posY);
    void draw(sf::RenderWindow& window);

    const float PTM_RATIO = 32.f;
    const int HALF_WIDTH = 32;
    const int HALF_HEIGHT = 16;
    int armor;
    bool flaggedToErase = false;

    b2Body* tileBody;
    sf::Sprite sprite;
};

Tile.cpp

Tile::Tile(b2World* …
Run Code Online (Sandbox Code Playgroud)

c++ compiler-errors vector deleted-functions

2
推荐指数
1
解决办法
8809
查看次数

在基类中删除复制和移动构造函数/赋值运算符是否足够?

如果我有一个抽象基类,并且想使所有派生类不可复制且不可移动,那么声明在基类中删除的这些特殊成员函数就足够了吗?我想确保我的整个类层次结构是不可复制和不可移动的,并且想知道是否可以不必在每个派生类中声明这4个特殊成员函数都已删除。我看到一个SO答案,似乎暗示着派生类尽管已从基类中删除了,但仍可以显式声明副本或移动构造函数,但以下示例在尝试定义默认的副本赋值运算符时导致编译错误,因此我不确定。这是错误:

named_class.cc:15:15:错误:默认情况下,此副本构造函数将在其第一个声明DerivedClass :: DerivedClass(const DerivedClass&)= default之后将其删除;

named_class.h:9:22:注意:“ DerivedClass”的副本构造函数被隐式删除,因为基类“ virtual_functions :: BaseClass”具有已删除的副本构造函数类DerivedClass:public BaseClass {

base_class.h:11:3:注意:“ BaseClass”已明确标记为已删除,此处BaseClass(const BaseClass&)= delete;

// base_class.h
class BaseClass {
public:
  BaseClass(const BaseClass &) = delete;
  BaseClass(BaseClass &&) = delete;
  BaseClass &operator=(const BaseClass &) = delete;
  BaseClass &operator=(BaseClass &&) = delete;
  virtual ~BaseClass() = default;
  virtual bool doSomething() = 0;

protected:
  BaseClass(std::string name);

private:
  std::string name_;
};

// derived_class.h
class DerivedClass : public BaseClass {
public:
  DerivedClass();
  DerivedClass(const DerivedClass &);
  bool doSomething() override;
};

// derived_class.cc
DerivedClass::DerivedClass(const DerivedClass …
Run Code Online (Sandbox Code Playgroud)

c++ deleted-functions c++11

2
推荐指数
2
解决办法
395
查看次数

std::map:当元素不可默认构造时创建/替换元素

假设您有一个不可默认构造的类。

class A {
  private:
    int a;
  public:
    A() = delete;
    A(int a0) : a(a0) {}
};
Run Code Online (Sandbox Code Playgroud)

现在,我们有一些地图 Int --> A, std::map<int, A> mapping。假设我们要为某个键 0 创建一个新映射,如果键存在,我们要替换旧值。对默认可构造类执行此操作的方法是:

mapping[0] = A(4);
Run Code Online (Sandbox Code Playgroud)

然而,这对于类 A 将失败,因为 operator[] 首先构造 A 的默认实例,然后才分配 的值A(4)。通常这样做的一种方法(即对于不可默认构造的类)是这样的:

auto it = mapping.find(0);
if (it == mapping.end()) {
  mapping.insert(0, A(4));
}
else {
  it->second = A(4);
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:这真的是(C++)预期的方法吗?我觉得这不可能是对的;作为一名程序员,我不想为这么少的代码编写这么多代码。但似乎没有简单的出路:我已经查找了常见的地图方法(插入、emplace、emplace_hint),如果键已经存在,它们都不会执行任何操作。

c++ stdmap std deleted-functions

2
推荐指数
1
解决办法
155
查看次数