标签: temporary-objects

初始化具有函数返回值的对象时未复制的复制构造函数

请考虑以下代码:

#include <iostream>

using namespace std;

class A
{
    public:
        int a;
        A(): a(5)
        {
           cout << "Constructor\n";
        }
        A(const A &b)
        {
            a = b.a;
            cout << "Copy Constructor\n";
        }
        A fun(A a)
        {
            return a;
        }
};

int main()
{
    A a, c;
    A b = a.fun(c);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

上面代码的输出g++ file.cpp是:

Constructor
Constructor
Copy Constructor
Copy Constructor
Run Code Online (Sandbox Code Playgroud)

上面代码的输出g++ -fno-elide-constructors file.cpp是:

Constructor
Constructor
Copy Constructor
Copy Constructor
Copy Constructor
Run Code Online (Sandbox Code Playgroud)

我知道返回值优化.我的问题是哪个复制构造函数的调用被删除(返回期间的临时对象或被复制到b的返回对象)?

如果省略的复制构造函数是用于创建b的构造函数,那么如何创建b(因为在这种情况下也没有构造函数调用)?

如果我替换行A b …

c++ copy-constructor temporary-objects return-value-optimization copy-elision

9
推荐指数
1
解决办法
605
查看次数

在C中获取临时(复合文字)参数的地址

我无法想象这已经不是重复了,但我不能轻易找到答案,因为特别针对C++的更复杂的场景似乎主宰了讨论0.

在C99中取一个函数调用的参数列表中的临时构造地址是否合法?

例如,类似于init_listinit_desig_init如下的内容:

typedef struct {
  int x;
  int y;
} point_t;

int manhattan(point_t *p) {
  return p->x + p->y;
}

int init_list() {
  return manhattan(&(point_t){1, 2});
}

int init_desig_init() {
  return manhattan(&(point_t){.x = 1});
}
Run Code Online (Sandbox Code Playgroud)

三大1 似乎编译好了,但我实际上找不到一个参考,解释临时的生命周期至少会通过函数调用来扩展.


0事实证明,根据下面MM的回答,我的部分搜索问题是因为我正在寻找有关临时数据的信息,而这个特定初始化结构的正确C术语是复合文字.

1我应该称之为"大跨平台三",尊重MSVC,但实际上我的意思是"C编译器神棒支持".

c c99 initializer language-lawyer temporary-objects

9
推荐指数
1
解决办法
306
查看次数

在结构体的STL Map中,为什么"[]"运算符会导致结构体的dtor被多次调用2次?

我创建了一个简单的测试用例,展示了我在一个更大的代码库中注意到的奇怪行为.这个测试用例如下.我依靠STL Map的"[]"运算符来创建指向这种结构的映射中的结构的指针.在下面的测试用例中,线...

TestStruct *thisTestStruct = &testStructMap["test"];
Run Code Online (Sandbox Code Playgroud)

...给我指针(并在地图中创建一个新条目).我注意到的奇怪之处在于,这一行不仅会导致地图中的新条目被创建(因为"[]"运算符),但由于某种原因,它会导致结构体的析构函数被多次调用两次.我显然错过了一些东西 - 非常感谢任何帮助!谢谢!

#include <iostream>
#include <string>
#include <map>

using namespace std;
struct TestStruct;

int main (int argc, char * const argv[]) {

    map<string, TestStruct> testStructMap;

    std::cout << "Marker One\n";

    //why does this line cause "~TestStruct()" to be invoked twice?
    TestStruct *thisTestStruct = &testStructMap["test"];

    std::cout << "Marker Two\n";

    return 0;
}

struct TestStruct{
    TestStruct(){
        std::cout << "TestStruct Constructor!\n";
    }

    ~TestStruct(){
        std::cout << "TestStruct Destructor!\n";
    }
};
Run Code Online (Sandbox Code Playgroud)

上面的代码输出以下内容......

/*
Marker One
TestStruct Constructor!             //makes sense …
Run Code Online (Sandbox Code Playgroud)

c++ constructor stl copy-constructor temporary-objects

8
推荐指数
3
解决办法
1634
查看次数

SWIG Python包装器中临时对象的生命周期(?)

2月12日编辑

我最近刚刚使用一些SWIG生成的Python包装器为一些C++类提出了一个奇怪的崩溃.似乎SWIG和Python的结合有点急于清理临时值.事实上,他们非常渴望在他们还在使用的时候进行清理.一个显着浓缩的版本看起来像这样:

/* Example.hpp */
struct Foo {
    int value;
    ~Foo();
};

struct Bar {
    Foo theFoo;
    Bar();
};

/* Example.cpp */
#include "Example.hpp"
Bar::Bar()  {theFoo.value=1;}
Foo::~Foo() {value=0;}

/* Example.i */
%module Example
%{
#include "Example.hpp"
%}
%include "Example.hpp"
Run Code Online (Sandbox Code Playgroud)

我在.i文件上运行SWIG(1.3.37),然后在Python中运行:

Python 2.4.3 (#1, Sept 17 2008, 16:07:08)
[GCC 4.1.2 20071124 (Red Hat 4.1.2-41)] on linux2
Type "help", "copyright", "credits", or "license" for more information.
>>> from Example import Bar
>>> b=Bar()
>>> print b.theFoo.value      # expect '1', since Bar's constructor …
Run Code Online (Sandbox Code Playgroud)

c++ python swig lifetime temporary-objects

8
推荐指数
1
解决办法
1841
查看次数

vector <T> :: swap和临时对象

代码如下:

#include <vector>

int main()
{
    vector<int> v1(5,1);
    v1.swap(vector<int> ());  //try to swap v1 with a temporary vector object
}
Run Code Online (Sandbox Code Playgroud)

上面的代码无法编译,错误:

error: no matching function for call to ‘std::vector<int, std::allocator<int> >::swap(std::vector<int, std::allocator<int> >)’
Run Code Online (Sandbox Code Playgroud)

但是,如果我将代码更改为类似的东西,它可以编译:

int main()
{
    vector<int> v1(5,1);
    vector<int> ().swap(v1);
}
Run Code Online (Sandbox Code Playgroud)

为什么?

c++ swap vector temporary-objects

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

C++返回临时对象的混乱

我有一个相当基本的C++问题,考虑一个函数,它接受一些输入参数并std::string从这些参数中创建一个,如下所示:

std::string constructString( int some_parameter ) {

    std::stringstream ss;

    // Construct a string (arbitrarily complex)
    ss << "Some parameter is " << some_parameter << " right now";

    return ss.str();    //Am I not returning a temporary object here?
}
Run Code Online (Sandbox Code Playgroud)

我知道stringstream-object在函数返回时会超出范围,但是不会使构造的字符串失效吗?

如果我将返回类型更改为const char *并返回,会发生什么ss.str().c_str()

像上面这样的代码似乎有效,但我怀疑这只是因为当我使用它时,包含'临时'对象的内存还没有被其他东西覆盖?

我不得不承认,在这种情况下我总是很困惑,如果有人可以向我解释这整个"临时对象"(或者只是指向正确的方向),我会很感激.

thx提前

c++ temporary-objects

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

析构函数调用逗号分隔的表达式

考虑以下示例程序:

#include <iostream>
using namespace std;
struct t
{
    ~t() {cout << "destroyed\n"; }
};
int main()
{
    cout << "test\n";
    t(), cout << "doing stuff\n";
    cout << "end\n";
}
Run Code Online (Sandbox Code Playgroud)

我从GCC 4.9.2获得的输出是:

test 
doing stuff 
destroyed 
end
Run Code Online (Sandbox Code Playgroud)

cpp.sh链接:http://cpp.sh/3cvm

但是根据关于逗号运算符的cppreference:

在逗号表达式E1,E2中,评估表达式E1,丢弃其结果,并且在评估表达式E2开始之前完成其副作用

我希望~t()以前能打电话给我cout << "doing stuff"

这是标准行为吗?如果是这样,标准中的定义在哪里?

c++ object-lifetime comma-operator language-lawyer temporary-objects

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

在c ++ 11中将指针传递给临时?

我有一个现有的功能:

void foo(const Key* key = nullptr)
{
  // uses the key
}
Run Code Online (Sandbox Code Playgroud)

我想将它指向临时Key对象(即rvalue),如:

foo(&Key());
Run Code Online (Sandbox Code Playgroud)

这会导致编译错误,但是在c ++ 11/14中有一种方法可以做到这一点吗?我当然可以这样做:

Key key;
foo(&key);
Run Code Online (Sandbox Code Playgroud)

但我不需要对象Key,我只需要它在foo()和foo()中

或者我可以这样做:

foo(new Key());
Run Code Online (Sandbox Code Playgroud)

但是这个对象不会被删除.

c++ temporary-objects c++11 c++14 c++17

7
推荐指数
3
解决办法
956
查看次数

如何实现具有自然外观语法的线程安全容器?

前言

下面的代码导致未定义的行为,如果按原样使用:

vector<int> vi;
...
vi.push_back(1);  // thread-1
...
vi.pop(); // thread-2
Run Code Online (Sandbox Code Playgroud)

传统的方法是修复它std::mutex:

std::lock_guard<std::mutex> lock(some_mutex_specifically_for_vi);
vi.push_back(1);
Run Code Online (Sandbox Code Playgroud)

但是,随着代码的增长,这样的事情开始变得麻烦,因为每次在方法之前都会有锁.而且,对于每个对象,我们可能必须保持互斥锁.

目的

在不影响访问对象和声明显式互斥体的语法的情况下,我想创建一个模板,使其完成所有样板工作.例如

Concurrent<vector<int>> vi;  // specific `vi` mutex is auto declared in this wrapper
...
vi.push_back(1); // thread-1: locks `vi` only until `push_back()` is performed
...
vi.pop ()  // thread-2: locks `vi` only until `pop()` is performed
Run Code Online (Sandbox Code Playgroud)

在当前的C++中,实现这一目标是不可能的.不过,我试图在那里,如果只是改变代码vi.vi->,然后按预期在上面的代码中的注释工作的事情.

// The `Class` member is accessed via `->` instead of `.` operator
// For `const` object, it's assumed …
Run Code Online (Sandbox Code Playgroud)

c++ templates thread-safety temporary-objects c++14

7
推荐指数
3
解决办法
401
查看次数

您可以取消引用临时数组吗?

考虑以下代码:

void foo() {
    int arr[1];
    *arr; // OK

    using T = int[1];
    *T{}; // OK for Clang and MSVC
          // GCC error: taking address of temporary array
}
Run Code Online (Sandbox Code Playgroud)

在 Compiler Explorer 中查看实时代码

我的直觉是,这*T{}应该会导致数组到指针的转换,并且间接寻址的格式良好。不过,我对此并不完全确定。

GCC 是对的还是这是一个错误?是故意的,为了防止开发人员犯错误吗?毕竟,您通常不会取消引用数组。这有记录在任何地方吗?

免责声明
CWG Issue 2548已确认“通过数组纯右值的间接寻址现在也无效”。@StoryTeller 的答案是错误的,并通过假设这也适用于 来误解目标类型*T{}的含义,但该表达式不是指针的初始化。

更多讨论请参见编辑问题EDIT 6555

c++ gcc language-lawyer temporary-objects c++20

7
推荐指数
1
解决办法
382
查看次数