我想知道为什么这个程序不能编译(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();
}
根据我的期望,删除的拷贝构造函数应该让其他ActionDecorator实例构造ActionDecorator,因为它是Action的多态类型.相反,我必须显式地将ActionDecorator实例转换为Action并且因为编译器抱怨尝试引用已删除的复制构造函数.是否有一些解释这种行为的标准规则?
我在代码库中广泛使用了std :: mutex.但是,其中一个类只是不允许我在其实例变量列表中添加互斥锁.我正在使用以下内容简单地实例化互斥锁 -
std::mutex myMutex;
我将上述语句添加到类成员列表的私有部分.
我收到以下错误 -
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'
我试图添加互斥锁的类被复制.
正如我所说的,我在我的代码库中使用了互斥锁,所以我可以在一个地方实例化互斥锁,而我可以在所有其他地方实例化,这是非常奇怪的.你能告诉我这里出了什么问题吗?
我有以下类示例,从较大的项目中简化.它基于一个日志框架,它使用记录器的作用域来终止析构函数中的日志条目.
下面的代码将无法编译,因为构造函数是一个隐式删除的函数(编辑:不是真),这似乎与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;
}
请注意,标记为"正常工作"的行就是这样做的.它似乎实例化了一个匿名Container对象,它包含一个新的std::ostringstream …
我正在尝试合并两个向量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;
}
#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;
}
例如,如果我这样使用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;
}
我会成功获得输出i = 3,所以我无法理解为什么我会得到如此不同的答案.
给出以下玩具代码:
class X
{
public:
    X() { }
    X(const X&) { }
    //X(X&&) = delete;
};
int main()
{
    X x;
    X y = std::move(x);
}
我知道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);直接与 …
以下代码
#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;
}
可能导致崩溃,因为原始矢量已经在那里被破坏.在引入rvalue-reference之后的C++ 2011(c ++ 0x)中,如果vector参数是rvalue ,则可以使用已删除的函数声明来完全禁止调用at
std::string const& at(std::vector<std::string>&&, int) = delete;
这看起来不错,但以下代码仍会导致崩溃
int main()
{
    std::string const& s = mkvec()[0];
    std::cout << s << std::endl; // D'oh!
    return 0;
} …我是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
当我尝试使用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* …如果我有一个抽象基类,并且想使所有派生类不可复制且不可移动,那么声明在基类中删除的这些特殊成员函数就足够了吗?我想确保我的整个类层次结构是不可复制和不可移动的,并且想知道是否可以不必在每个派生类中声明这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 …假设您有一个不可默认构造的类。
class A {
  private:
    int a;
  public:
    A() = delete;
    A(int a0) : a(a0) {}
};
现在,我们有一些地图 Int --> A, std::map<int, A> mapping。假设我们要为某个键 0 创建一个新映射,如果键存在,我们要替换旧值。对默认可构造类执行此操作的方法是:
mapping[0] = A(4);
然而,这对于类 A 将失败,因为 operator[] 首先构造 A 的默认实例,然后才分配 的值A(4)。通常这样做的一种方法(即对于不可默认构造的类)是这样的:
auto it = mapping.find(0);
if (it == mapping.end()) {
  mapping.insert(0, A(4));
}
else {
  it->second = A(4);
}
我的问题是:这真的是(C++)预期的方法吗?我觉得这不可能是对的;作为一名程序员,我不想为这么少的代码编写这么多代码。但似乎没有简单的出路:我已经查找了常见的地图方法(插入、emplace、emplace_hint),如果键已经存在,它们都不会执行任何操作。